From 3415941c3e560502aee9e8d150fcb34068841b26 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Thu, 5 Oct 2023 14:50:48 +0700 Subject: [PATCH 001/210] refactor: move the wrapper to its own crate --- Cargo.lock | 5 +++++ Cargo.toml | 1 + crates/cli/Cargo.toml | 1 + crates/cli/src/fs.rs | 13 ++----------- crates/cli/src/package_import.rs | 5 +++-- crates/fs/Cargo.toml | 11 +++++++++++ crates/fs/src/lib.rs | 11 +++++++++++ 7 files changed, 34 insertions(+), 13 deletions(-) create mode 100644 crates/fs/Cargo.toml create mode 100644 crates/fs/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index fa7d7ddf6..3b587f7c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1288,6 +1288,7 @@ dependencies = [ "pacquet_cafs", "pacquet_diagnostics", "pacquet_executor", + "pacquet_fs", "pacquet_lockfile", "pacquet_npmrc", "pacquet_package_json", @@ -1322,6 +1323,10 @@ dependencies = [ "pacquet_diagnostics", ] +[[package]] +name = "pacquet_fs" +version = "0.0.1" + [[package]] name = "pacquet_lockfile" version = "0.0.1" diff --git a/Cargo.toml b/Cargo.toml index c86ac05bf..36d907d7f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ repository = "https://github.com/anonrig/pacquet" [workspace.dependencies] # Crates pacquet_cli = { path = "crates/cli" } +pacquet_fs = { path = "crates/fs" } pacquet_registry = { path = "crates/registry" } pacquet_tarball = { path = "crates/tarball" } pacquet_package_json = { path = "crates/package_json" } diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 292ed1c80..39d1c4f25 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -17,6 +17,7 @@ path = "src/bin/main.rs" [dependencies] pacquet_cafs = { workspace = true } pacquet_executor = { workspace = true } +pacquet_fs = { workspace = true } pacquet_lockfile = { workspace = true } pacquet_npmrc = { workspace = true } pacquet_package_json = { workspace = true } diff --git a/crates/cli/src/fs.rs b/crates/cli/src/fs.rs index 441a22eb7..52b943df0 100644 --- a/crates/cli/src/fs.rs +++ b/crates/cli/src/fs.rs @@ -1,14 +1,5 @@ -use std::{io, os, path::Path}; - -#[cfg(unix)] -pub fn symlink_dir(original: &Path, link: &Path) -> io::Result<()> { - os::unix::fs::symlink(original, link) -} - -#[cfg(windows)] -pub fn symlink_dir(original: &Path, link: &Path) -> io::Result<()> { - os::windows::fs::symlink_dir(original, link) -} +#[cfg(test)] +use std::path::Path; #[cfg(test)] pub fn get_filenames_in_folder(path: &Path) -> Vec { diff --git a/crates/cli/src/package_import.rs b/crates/cli/src/package_import.rs index f3027a149..63be7ca1e 100644 --- a/crates/cli/src/package_import.rs +++ b/crates/cli/src/package_import.rs @@ -8,6 +8,7 @@ use std::{ use crate::package_manager::{AutoImportError, PackageManagerError}; use pacquet_diagnostics::tracing; +use pacquet_fs::symlink_dir; use pacquet_lockfile::{ DependencyPath, PackageSnapshot, PackageSnapshotDependency, PkgNameVerPeer, }; @@ -46,7 +47,7 @@ impl ImportMethodImpl for PackageImportMethod { if let Some(parent_dir) = symlink_to.parent() { fs::create_dir_all(parent_dir)?; } - crate::fs::symlink_dir(save_path, symlink_to)?; + symlink_dir(save_path, symlink_to)?; } } _ => panic!("Not implemented yet"), @@ -143,7 +144,7 @@ pub fn symlink_pkg(symlink_target: &Path, symlink_path: &Path) { if let Some(parent) = symlink_path.parent() { fs::create_dir_all(parent).expect("make sure node_modules exist"); // TODO: proper error propagation } - if let Err(error) = crate::fs::symlink_dir(symlink_target, symlink_path) { + if let Err(error) = symlink_dir(symlink_target, symlink_path) { match error.kind() { ErrorKind::AlreadyExists => {} _ => panic!( diff --git a/crates/fs/Cargo.toml b/crates/fs/Cargo.toml new file mode 100644 index 000000000..6bca1c736 --- /dev/null +++ b/crates/fs/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "pacquet_fs" +description = "Filesystem utility functions used by pacquet" +version = "0.0.1" +publish = false +authors.workspace = true +edition.workspace = true +homepage.workspace = true +keywords.workspace = true +license.workspace = true +repository.workspace = true diff --git a/crates/fs/src/lib.rs b/crates/fs/src/lib.rs new file mode 100644 index 000000000..d816a34bc --- /dev/null +++ b/crates/fs/src/lib.rs @@ -0,0 +1,11 @@ +use std::{io, os, path::Path}; + +/// Create a symlink to a directory. +/// +/// The `link` path will be a symbolic link pointing to `original`. +pub fn symlink_dir(original: &Path, link: &Path) -> io::Result<()> { + #[cfg(unix)] + return os::unix::fs::symlink(original, link); + #[cfg(windows)] + return os::windows::fs::symlink_dir(original, link); +} From 92faddeafc9b5149f2c129283b777f14dc5c76a8 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Thu, 5 Oct 2023 15:16:42 +0700 Subject: [PATCH 002/210] refactor: move symlink_pkg to package_manager --- Cargo.lock | 8 ++++++++ Cargo.toml | 21 +++++++++++---------- crates/cli/Cargo.toml | 19 ++++++++++--------- crates/cli/src/commands/install.rs | 2 +- crates/cli/src/package_import.rs | 18 +----------------- crates/package_manager/Cargo.toml | 14 ++++++++++++++ crates/package_manager/src/lib.rs | 3 +++ crates/package_manager/src/symlink_pkg.rs | 23 +++++++++++++++++++++++ 8 files changed, 71 insertions(+), 37 deletions(-) create mode 100644 crates/package_manager/Cargo.toml create mode 100644 crates/package_manager/src/lib.rs create mode 100644 crates/package_manager/src/symlink_pkg.rs diff --git a/Cargo.lock b/Cargo.lock index 3b587f7c6..705308945 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1292,6 +1292,7 @@ dependencies = [ "pacquet_lockfile", "pacquet_npmrc", "pacquet_package_json", + "pacquet_package_manager", "pacquet_registry", "pacquet_tarball", "pipe-trait", @@ -1369,6 +1370,13 @@ dependencies = [ "tempfile", ] +[[package]] +name = "pacquet_package_manager" +version = "0.0.1" +dependencies = [ + "pacquet_fs", +] + [[package]] name = "pacquet_registry" version = "0.0.1" diff --git a/Cargo.toml b/Cargo.toml index 36d907d7f..c2e0302d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,16 +13,17 @@ repository = "https://github.com/anonrig/pacquet" [workspace.dependencies] # Crates -pacquet_cli = { path = "crates/cli" } -pacquet_fs = { path = "crates/fs" } -pacquet_registry = { path = "crates/registry" } -pacquet_tarball = { path = "crates/tarball" } -pacquet_package_json = { path = "crates/package_json" } -pacquet_lockfile = { path = "crates/lockfile" } -pacquet_npmrc = { path = "crates/npmrc" } -pacquet_executor = { path = "crates/executor" } -pacquet_cafs = { path = "crates/cafs" } -pacquet_diagnostics = { path = "crates/diagnostics" } +pacquet_cli = { path = "crates/cli" } +pacquet_fs = { path = "crates/fs" } +pacquet_registry = { path = "crates/registry" } +pacquet_tarball = { path = "crates/tarball" } +pacquet_package_json = { path = "crates/package_json" } +pacquet_package_manager = { path = "crates/package_manager" } +pacquet_lockfile = { path = "crates/lockfile" } +pacquet_npmrc = { path = "crates/npmrc" } +pacquet_executor = { path = "crates/executor" } +pacquet_cafs = { path = "crates/cafs" } +pacquet_diagnostics = { path = "crates/diagnostics" } # Dependencies async-recursion = { version = "1.0.5" } diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 39d1c4f25..de9eeb989 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -15,15 +15,16 @@ name = "pacquet" path = "src/bin/main.rs" [dependencies] -pacquet_cafs = { workspace = true } -pacquet_executor = { workspace = true } -pacquet_fs = { workspace = true } -pacquet_lockfile = { workspace = true } -pacquet_npmrc = { workspace = true } -pacquet_package_json = { workspace = true } -pacquet_registry = { workspace = true } -pacquet_tarball = { workspace = true } -pacquet_diagnostics = { workspace = true } +pacquet_cafs = { workspace = true } +pacquet_executor = { workspace = true } +pacquet_fs = { workspace = true } +pacquet_lockfile = { workspace = true } +pacquet_npmrc = { workspace = true } +pacquet_package_json = { workspace = true } +pacquet_package_manager = { workspace = true } +pacquet_registry = { workspace = true } +pacquet_tarball = { workspace = true } +pacquet_diagnostics = { workspace = true } async-recursion = { workspace = true } clap = { workspace = true } diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/commands/install.rs index 29ae2f268..37106f2c6 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/commands/install.rs @@ -1,5 +1,4 @@ use crate::package::{install_package_from_registry, install_single_package_to_virtual_store}; -use crate::package_import::symlink_pkg; use crate::package_manager::{PackageManager, PackageManagerError}; use async_recursion::async_recursion; use clap::Parser; @@ -9,6 +8,7 @@ use pacquet_lockfile::{ DependencyPath, Lockfile, PackageSnapshot, PkgName, PkgNameVerPeer, RootProjectSnapshot, }; use pacquet_package_json::DependencyGroup; +use pacquet_package_manager::symlink_pkg; use pacquet_registry::PackageVersion; use pipe_trait::Pipe; use rayon::prelude::*; diff --git a/crates/cli/src/package_import.rs b/crates/cli/src/package_import.rs index 63be7ca1e..45c18ac2a 100644 --- a/crates/cli/src/package_import.rs +++ b/crates/cli/src/package_import.rs @@ -2,7 +2,6 @@ use std::{ collections::HashMap, ffi::OsString, fs, - io::ErrorKind, path::{Path, PathBuf}, }; @@ -13,6 +12,7 @@ use pacquet_lockfile::{ DependencyPath, PackageSnapshot, PackageSnapshotDependency, PkgNameVerPeer, }; use pacquet_npmrc::PackageImportMethod; +use pacquet_package_manager::symlink_pkg; use rayon::prelude::*; pub trait ImportMethodImpl { @@ -137,19 +137,3 @@ fn auto_import(source_file: &Path, target_link: &Path) -> Result<(), AutoImportE Ok(()) } - -pub fn symlink_pkg(symlink_target: &Path, symlink_path: &Path) { - // NOTE: symlink target in pacquet is absolute yet in pnpm is relative - // TODO: change symlink target to relative - if let Some(parent) = symlink_path.parent() { - fs::create_dir_all(parent).expect("make sure node_modules exist"); // TODO: proper error propagation - } - if let Err(error) = symlink_dir(symlink_target, symlink_path) { - match error.kind() { - ErrorKind::AlreadyExists => {} - _ => panic!( - "Failed to create symlink at {symlink_path:?} to {symlink_target:?}: {error}" - ), // TODO: proper error propagation - } - } -} diff --git a/crates/package_manager/Cargo.toml b/crates/package_manager/Cargo.toml new file mode 100644 index 000000000..e4b5a8be6 --- /dev/null +++ b/crates/package_manager/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "pacquet_package_manager" +version = "0.0.1" +publish = false +authors.workspace = true +description.workspace = true +edition.workspace = true +homepage.workspace = true +keywords.workspace = true +license.workspace = true +repository.workspace = true + +[dependencies] +pacquet_fs = { workspace = true } diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs new file mode 100644 index 000000000..372b9145d --- /dev/null +++ b/crates/package_manager/src/lib.rs @@ -0,0 +1,3 @@ +mod symlink_pkg; + +pub use symlink_pkg::symlink_pkg; diff --git a/crates/package_manager/src/symlink_pkg.rs b/crates/package_manager/src/symlink_pkg.rs new file mode 100644 index 000000000..d4b79f7dd --- /dev/null +++ b/crates/package_manager/src/symlink_pkg.rs @@ -0,0 +1,23 @@ +use pacquet_fs::symlink_dir; +use std::{fs, io::ErrorKind, path::Path}; + +/// Create symlink for a package. +/// +/// * If ancestors of `symlink_path` don't exist, they will be created recursively. +/// * If `symlink_path` already exists, skip. +/// * If `symlink_path` doesn't exist, a symlink pointing to `symlink_target` will be created. +pub fn symlink_pkg(symlink_target: &Path, symlink_path: &Path) { + // NOTE: symlink target in pacquet is absolute yet in pnpm is relative + // TODO: change symlink target to relative + if let Some(parent) = symlink_path.parent() { + fs::create_dir_all(parent).expect("make sure node_modules exist"); // TODO: proper error propagation + } + if let Err(error) = symlink_dir(symlink_target, symlink_path) { + match error.kind() { + ErrorKind::AlreadyExists => {} + _ => panic!( + "Failed to create symlink at {symlink_path:?} to {symlink_target:?}: {error}" + ), // TODO: proper error propagation + } + } +} From 9604f467dddc8495d12e7ba796599cf20776edda Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 6 Oct 2023 15:03:45 +0700 Subject: [PATCH 003/210] refactor: move auto_import --- Cargo.lock | 3 ++ crates/cli/src/package_import.rs | 27 +------------ crates/cli/src/package_manager.rs | 18 +-------- crates/package_manager/Cargo.toml | 5 ++- crates/package_manager/src/auto_import.rs | 46 +++++++++++++++++++++++ crates/package_manager/src/lib.rs | 2 + 6 files changed, 58 insertions(+), 43 deletions(-) create mode 100644 crates/package_manager/src/auto_import.rs diff --git a/Cargo.lock b/Cargo.lock index 705308945..b28360008 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1374,7 +1374,10 @@ dependencies = [ name = "pacquet_package_manager" version = "0.0.1" dependencies = [ + "derive_more", + "miette", "pacquet_fs", + "reflink-copy", ] [[package]] diff --git a/crates/cli/src/package_import.rs b/crates/cli/src/package_import.rs index 45c18ac2a..202154d60 100644 --- a/crates/cli/src/package_import.rs +++ b/crates/cli/src/package_import.rs @@ -5,14 +5,14 @@ use std::{ path::{Path, PathBuf}, }; -use crate::package_manager::{AutoImportError, PackageManagerError}; +use crate::package_manager::PackageManagerError; use pacquet_diagnostics::tracing; use pacquet_fs::symlink_dir; use pacquet_lockfile::{ DependencyPath, PackageSnapshot, PackageSnapshotDependency, PkgNameVerPeer, }; use pacquet_npmrc::PackageImportMethod; -use pacquet_package_manager::symlink_pkg; +use pacquet_package_manager::{auto_import, symlink_pkg}; use rayon::prelude::*; pub trait ImportMethodImpl { @@ -114,26 +114,3 @@ pub fn create_virtdir_by_snapshot( Ok(()) } - -fn auto_import(source_file: &Path, target_link: &Path) -> Result<(), AutoImportError> { - if target_link.exists() { - return Ok(()); - } - - if let Some(parent_dir) = target_link.parent() { - fs::create_dir_all(parent_dir).map_err(|error| AutoImportError::CreateDir { - dirname: parent_dir.to_path_buf(), - error, - })?; - } - - reflink_copy::reflink_or_copy(source_file, target_link).map_err(|error| { - AutoImportError::CreateLink { - from: source_file.to_path_buf(), - to: target_link.to_path_buf(), - error, - } - })?; // TODO: add hardlink - - Ok(()) -} diff --git a/crates/cli/src/package_manager.rs b/crates/cli/src/package_manager.rs index d80b054c1..2bb47484d 100644 --- a/crates/cli/src/package_manager.rs +++ b/crates/cli/src/package_manager.rs @@ -7,25 +7,9 @@ use pacquet_diagnostics::{ use pacquet_lockfile::Lockfile; use pacquet_npmrc::Npmrc; use pacquet_package_json::PackageJson; +use pacquet_package_manager::AutoImportError; use pacquet_tarball::Cache; -#[derive(Error, Debug, Diagnostic)] -pub enum AutoImportError { - #[error("cannot create directory at {dirname:?}: {error}")] - CreateDir { - dirname: PathBuf, - #[source] - error: io::Error, - }, - #[error("fail to create a link from {from:?} to {to:?}: {error}")] - CreateLink { - from: PathBuf, - to: PathBuf, - #[source] - error: io::Error, - }, -} - #[derive(Error, Debug, Diagnostic)] #[non_exhaustive] pub enum PackageManagerError { diff --git a/crates/package_manager/Cargo.toml b/crates/package_manager/Cargo.toml index e4b5a8be6..7048041a9 100644 --- a/crates/package_manager/Cargo.toml +++ b/crates/package_manager/Cargo.toml @@ -11,4 +11,7 @@ license.workspace = true repository.workspace = true [dependencies] -pacquet_fs = { workspace = true } +derive_more = { workspace = true } +pacquet_fs = { workspace = true } +reflink-copy = { workspace = true } +miette = { workspace = true } diff --git a/crates/package_manager/src/auto_import.rs b/crates/package_manager/src/auto_import.rs new file mode 100644 index 000000000..04af047a0 --- /dev/null +++ b/crates/package_manager/src/auto_import.rs @@ -0,0 +1,46 @@ +use derive_more::{Display, Error}; +use miette::Diagnostic; +use std::{ + fs, io, + path::{Path, PathBuf}, +}; + +#[derive(Debug, Display, Error, Diagnostic)] +pub enum AutoImportError { + #[display(fmt = "cannot create directory at {dirname:?}: {error}")] + CreateDir { + dirname: PathBuf, + #[error(source)] + error: io::Error, + }, + #[display(fmt = "fail to create a link from {from:?} to {to:?}: {error}")] + CreateLink { + from: PathBuf, + to: PathBuf, + #[error(source)] + error: io::Error, + }, +} + +pub fn auto_import(source_file: &Path, target_link: &Path) -> Result<(), AutoImportError> { + if target_link.exists() { + return Ok(()); + } + + if let Some(parent_dir) = target_link.parent() { + fs::create_dir_all(parent_dir).map_err(|error| AutoImportError::CreateDir { + dirname: parent_dir.to_path_buf(), + error, + })?; + } + + reflink_copy::reflink_or_copy(source_file, target_link).map_err(|error| { + AutoImportError::CreateLink { + from: source_file.to_path_buf(), + to: target_link.to_path_buf(), + error, + } + })?; // TODO: add hardlink + + Ok(()) +} diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index 372b9145d..313b9c367 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -1,3 +1,5 @@ +mod auto_import; mod symlink_pkg; +pub use auto_import::{auto_import, AutoImportError}; pub use symlink_pkg::symlink_pkg; From 751c94395c0c5303a8fa3770f9978f574d73d6bf Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 6 Oct 2023 18:18:55 +0700 Subject: [PATCH 004/210] refactor: rearrange dependencies --- crates/package_manager/Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/package_manager/Cargo.toml b/crates/package_manager/Cargo.toml index 7048041a9..85d3e5f4d 100644 --- a/crates/package_manager/Cargo.toml +++ b/crates/package_manager/Cargo.toml @@ -11,7 +11,8 @@ license.workspace = true repository.workspace = true [dependencies] -derive_more = { workspace = true } pacquet_fs = { workspace = true } + +derive_more = { workspace = true } reflink-copy = { workspace = true } miette = { workspace = true } From 05e79287a965e4e1bd29bbc38854f3b5aaa1b0a4 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 6 Oct 2023 19:29:52 +0700 Subject: [PATCH 005/210] refactor: move create_virtdir_by_snapshot --- Cargo.lock | 3 + crates/cli/src/package.rs | 6 +- crates/cli/src/package_import.rs | 63 +----------------- crates/cli/src/package_manager.rs | 6 +- crates/package_manager/Cargo.toml | 5 +- crates/package_manager/src/lib.rs | 2 + crates/package_manager/src/virtual_dir.rs | 79 +++++++++++++++++++++++ 7 files changed, 96 insertions(+), 68 deletions(-) create mode 100644 crates/package_manager/src/virtual_dir.rs diff --git a/Cargo.lock b/Cargo.lock index b28360008..e69cdac2a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1377,6 +1377,9 @@ dependencies = [ "derive_more", "miette", "pacquet_fs", + "pacquet_lockfile", + "pacquet_npmrc", + "rayon", "reflink-copy", ] diff --git a/crates/cli/src/package.rs b/crates/cli/src/package.rs index bd75fa951..aefbfab5e 100644 --- a/crates/cli/src/package.rs +++ b/crates/cli/src/package.rs @@ -1,9 +1,7 @@ -use crate::{ - package_import::{create_virtdir_by_snapshot, ImportMethodImpl}, - package_manager::PackageManagerError, -}; +use crate::{package_import::ImportMethodImpl, package_manager::PackageManagerError}; use pacquet_lockfile::{DependencyPath, LockfileResolution, PackageSnapshot, PkgNameVerPeer}; use pacquet_npmrc::Npmrc; +use pacquet_package_manager::create_virtdir_by_snapshot; use pacquet_registry::{Package, PackageVersion}; use pacquet_tarball::{download_tarball_to_store, Cache}; use pipe_trait::Pipe; diff --git a/crates/cli/src/package_import.rs b/crates/cli/src/package_import.rs index 202154d60..e8c2524c1 100644 --- a/crates/cli/src/package_import.rs +++ b/crates/cli/src/package_import.rs @@ -8,11 +8,8 @@ use std::{ use crate::package_manager::PackageManagerError; use pacquet_diagnostics::tracing; use pacquet_fs::symlink_dir; -use pacquet_lockfile::{ - DependencyPath, PackageSnapshot, PackageSnapshotDependency, PkgNameVerPeer, -}; use pacquet_npmrc::PackageImportMethod; -use pacquet_package_manager::{auto_import, symlink_pkg}; +use pacquet_package_manager::auto_import; use rayon::prelude::*; pub trait ImportMethodImpl { @@ -56,61 +53,3 @@ impl ImportMethodImpl for PackageImportMethod { Ok(()) } } - -/// This function does 2 things: -/// 1. Install the files from `cas_paths` -/// 2. Create the symlink layout -/// -/// **TODO:** may break this function into 2 later -pub fn create_virtdir_by_snapshot( - dependency_path: &DependencyPath, - virtual_store_dir: &Path, - cas_paths: &HashMap, - import_method: PackageImportMethod, - package_snapshot: &PackageSnapshot, -) -> Result<(), PackageManagerError> { - assert_eq!( - import_method, - PackageImportMethod::Auto, - "Only auto import method is supported, but {dependency_path} requires {import_method:?}", - ); - - // node_modules/.pacquet/pkg-name@x.y.z/node_modules - let virtual_node_modules_dir = virtual_store_dir - .join(dependency_path.package_specifier.to_virtual_store_name()) - .join("node_modules"); - fs::create_dir_all(&virtual_node_modules_dir).unwrap_or_else(|error| { - panic!("Failed to create directory at {virtual_node_modules_dir:?}: {error}") - }); // TODO: proper error propagation - - // 1. Install the files from `cas_paths` - let save_path = - virtual_node_modules_dir.join(dependency_path.package_specifier.name.to_string()); - if !save_path.exists() { - cas_paths.par_iter().try_for_each(|(cleaned_entry, store_path)| { - auto_import(store_path, &save_path.join(cleaned_entry)) - })?; - } - - // 2. Create the symlink layout - if let Some(dependencies) = &package_snapshot.dependencies { - dependencies.par_iter().for_each(|(name, spec)| { - let virtual_store_name = match spec { - PackageSnapshotDependency::PkgVerPeer(ver_peer) => { - let package_specifier = PkgNameVerPeer::new(name.clone(), ver_peer.clone()); // TODO: remove copying here - package_specifier.to_virtual_store_name() - } - PackageSnapshotDependency::DependencyPath(dependency_path) => { - dependency_path.package_specifier.to_virtual_store_name() - } - }; - let name_str = name.to_string(); - symlink_pkg( - &virtual_store_dir.join(virtual_store_name).join("node_modules").join(&name_str), - &virtual_node_modules_dir.join(&name_str), - ); - }); - } - - Ok(()) -} diff --git a/crates/cli/src/package_manager.rs b/crates/cli/src/package_manager.rs index 2bb47484d..b97ee493f 100644 --- a/crates/cli/src/package_manager.rs +++ b/crates/cli/src/package_manager.rs @@ -7,7 +7,7 @@ use pacquet_diagnostics::{ use pacquet_lockfile::Lockfile; use pacquet_npmrc::Npmrc; use pacquet_package_json::PackageJson; -use pacquet_package_manager::AutoImportError; +use pacquet_package_manager::{AutoImportError, CreateVirtdirError}; use pacquet_tarball::Cache; #[derive(Error, Debug, Diagnostic)] @@ -36,6 +36,10 @@ pub enum PackageManagerError { #[error(transparent)] #[diagnostic(transparent)] AutoImport(#[from] AutoImportError), + + #[error(transparent)] + #[diagnostic(transparent)] + CreateVirtdir(#[from] CreateVirtdirError), } pub struct PackageManager { diff --git a/crates/package_manager/Cargo.toml b/crates/package_manager/Cargo.toml index 85d3e5f4d..18c331f95 100644 --- a/crates/package_manager/Cargo.toml +++ b/crates/package_manager/Cargo.toml @@ -11,8 +11,11 @@ license.workspace = true repository.workspace = true [dependencies] -pacquet_fs = { workspace = true } +pacquet_fs = { workspace = true } +pacquet_lockfile = { workspace = true } +pacquet_npmrc = { workspace = true } derive_more = { workspace = true } +rayon = { workspace = true } reflink-copy = { workspace = true } miette = { workspace = true } diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index 313b9c367..fb88b7e2e 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -1,5 +1,7 @@ mod auto_import; mod symlink_pkg; +mod virtual_dir; pub use auto_import::{auto_import, AutoImportError}; pub use symlink_pkg::symlink_pkg; +pub use virtual_dir::{create_virtdir_by_snapshot, CreateVirtdirError}; diff --git a/crates/package_manager/src/virtual_dir.rs b/crates/package_manager/src/virtual_dir.rs new file mode 100644 index 000000000..e438a6f7e --- /dev/null +++ b/crates/package_manager/src/virtual_dir.rs @@ -0,0 +1,79 @@ +use crate::{auto_import, symlink_pkg, AutoImportError}; +use derive_more::{Display, Error}; +use miette::Diagnostic; +use pacquet_lockfile::{ + DependencyPath, PackageSnapshot, PackageSnapshotDependency, PkgNameVerPeer, +}; +use pacquet_npmrc::PackageImportMethod; +use rayon::prelude::*; +use std::{ + collections::HashMap, + ffi::OsString, + fs, + path::{Path, PathBuf}, +}; + +#[derive(Debug, Display, Error, Diagnostic)] +pub enum CreateVirtdirError { + #[diagnostic(transparent)] + AutoImport(#[error(source)] AutoImportError), +} + +/// This function does 2 things: +/// 1. Install the files from `cas_paths` +/// 2. Create the symlink layout +/// +/// **TODO:** may break this function into 2 later +pub fn create_virtdir_by_snapshot( + dependency_path: &DependencyPath, + virtual_store_dir: &Path, + cas_paths: &HashMap, + import_method: PackageImportMethod, + package_snapshot: &PackageSnapshot, +) -> Result<(), CreateVirtdirError> { + assert_eq!( + import_method, + PackageImportMethod::Auto, + "Only auto import method is supported, but {dependency_path} requires {import_method:?}", + ); + + // node_modules/.pacquet/pkg-name@x.y.z/node_modules + let virtual_node_modules_dir = virtual_store_dir + .join(dependency_path.package_specifier.to_virtual_store_name()) + .join("node_modules"); + fs::create_dir_all(&virtual_node_modules_dir).unwrap_or_else(|error| { + panic!("Failed to create directory at {virtual_node_modules_dir:?}: {error}") + }); // TODO: proper error propagation + + // 1. Install the files from `cas_paths` + let save_path = + virtual_node_modules_dir.join(dependency_path.package_specifier.name.to_string()); + if !save_path.exists() { + cas_paths.par_iter().try_for_each(|(cleaned_entry, store_path)| { + auto_import(store_path, &save_path.join(cleaned_entry)) + .map_err(CreateVirtdirError::AutoImport) + })?; + } + + // 2. Create the symlink layout + if let Some(dependencies) = &package_snapshot.dependencies { + dependencies.par_iter().for_each(|(name, spec)| { + let virtual_store_name = match spec { + PackageSnapshotDependency::PkgVerPeer(ver_peer) => { + let package_specifier = PkgNameVerPeer::new(name.clone(), ver_peer.clone()); // TODO: remove copying here + package_specifier.to_virtual_store_name() + } + PackageSnapshotDependency::DependencyPath(dependency_path) => { + dependency_path.package_specifier.to_virtual_store_name() + } + }; + let name_str = name.to_string(); + symlink_pkg( + &virtual_store_dir.join(virtual_store_name).join("node_modules").join(&name_str), + &virtual_node_modules_dir.join(&name_str), + ); + }); + } + + Ok(()) +} From 1cca0c59b55ae74b1c42c54a7bf9d304e6dd03ab Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 6 Oct 2023 22:37:56 +0700 Subject: [PATCH 006/210] refactor: rename a mod --- crates/package_manager/src/{auto_import.rs => import_pkg.rs} | 0 crates/package_manager/src/lib.rs | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename crates/package_manager/src/{auto_import.rs => import_pkg.rs} (100%) diff --git a/crates/package_manager/src/auto_import.rs b/crates/package_manager/src/import_pkg.rs similarity index 100% rename from crates/package_manager/src/auto_import.rs rename to crates/package_manager/src/import_pkg.rs diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index fb88b7e2e..84e54f705 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -1,7 +1,7 @@ -mod auto_import; +mod import_pkg; mod symlink_pkg; mod virtual_dir; -pub use auto_import::{auto_import, AutoImportError}; +pub use import_pkg::{auto_import, AutoImportError}; pub use symlink_pkg::symlink_pkg; pub use virtual_dir::{create_virtdir_by_snapshot, CreateVirtdirError}; From 3d81563d6b7ed75800a2dc100b909e4d76f70874 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 6 Oct 2023 23:02:17 +0700 Subject: [PATCH 007/210] refactor: move import package --- Cargo.lock | 1 + crates/cli/src/lib.rs | 1 - crates/cli/src/package.rs | 15 +++--- crates/cli/src/package_import.rs | 55 ------------------- crates/cli/src/package_manager.rs | 6 ++- crates/package_manager/Cargo.toml | 1 + crates/package_manager/src/import_pkg.rs | 68 ++++++++++++++++++++++++ crates/package_manager/src/lib.rs | 2 +- 8 files changed, 85 insertions(+), 64 deletions(-) delete mode 100644 crates/cli/src/package_import.rs diff --git a/Cargo.lock b/Cargo.lock index e69cdac2a..ea38cbbcd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1381,6 +1381,7 @@ dependencies = [ "pacquet_npmrc", "rayon", "reflink-copy", + "tracing", ] [[package]] diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index 924a620c7..934449fe0 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -1,7 +1,6 @@ mod commands; mod fs; mod package; -mod package_import; mod package_manager; use crate::package_manager::PackageManager; diff --git a/crates/cli/src/package.rs b/crates/cli/src/package.rs index aefbfab5e..7d0e73121 100644 --- a/crates/cli/src/package.rs +++ b/crates/cli/src/package.rs @@ -1,7 +1,8 @@ -use crate::{package_import::ImportMethodImpl, package_manager::PackageManagerError}; +use crate::package_manager::PackageManagerError; use pacquet_lockfile::{DependencyPath, LockfileResolution, PackageSnapshot, PkgNameVerPeer}; use pacquet_npmrc::Npmrc; use pacquet_package_manager::create_virtdir_by_snapshot; +use pacquet_package_manager::ImportPackage; use pacquet_registry::{Package, PackageVersion}; use pacquet_tarball::{download_tarball_to_store, Cache}; use pipe_trait::Pipe; @@ -70,11 +71,13 @@ async fn internal_fetch( .join("node_modules") .join(&package_version.name); - config.package_import_method.import( - &cas_paths, - &save_path, - &symlink_path.join(&package_version.name), - )?; + ImportPackage { + method: config.package_import_method, + cas_paths: &cas_paths, + save_path: &save_path, + symlink_path: &symlink_path.join(&package_version.name), + } + .import_pkg()?; Ok(()) } diff --git a/crates/cli/src/package_import.rs b/crates/cli/src/package_import.rs deleted file mode 100644 index e8c2524c1..000000000 --- a/crates/cli/src/package_import.rs +++ /dev/null @@ -1,55 +0,0 @@ -use std::{ - collections::HashMap, - ffi::OsString, - fs, - path::{Path, PathBuf}, -}; - -use crate::package_manager::PackageManagerError; -use pacquet_diagnostics::tracing; -use pacquet_fs::symlink_dir; -use pacquet_npmrc::PackageImportMethod; -use pacquet_package_manager::auto_import; -use rayon::prelude::*; - -pub trait ImportMethodImpl { - fn import( - &self, - cas_files: &HashMap, - save_path: &Path, - symlink_to: &Path, - ) -> Result<(), PackageManagerError>; -} - -impl ImportMethodImpl for PackageImportMethod { - fn import( - &self, - cas_files: &HashMap, - save_path: &Path, - symlink_to: &Path, - ) -> Result<(), PackageManagerError> { - tracing::info!(target: "pacquet::import", ?save_path, ?symlink_to, "Import package"); - match self { - PackageImportMethod::Auto => { - if !save_path.exists() { - cas_files - .into_par_iter() - .try_for_each(|(cleaned_entry, store_path)| { - auto_import(store_path, &save_path.join(cleaned_entry)) - }) - .expect("expected no write errors"); - } - - if !symlink_to.is_symlink() { - if let Some(parent_dir) = symlink_to.parent() { - fs::create_dir_all(parent_dir)?; - } - symlink_dir(save_path, symlink_to)?; - } - } - _ => panic!("Not implemented yet"), - } - - Ok(()) - } -} diff --git a/crates/cli/src/package_manager.rs b/crates/cli/src/package_manager.rs index b97ee493f..f88705042 100644 --- a/crates/cli/src/package_manager.rs +++ b/crates/cli/src/package_manager.rs @@ -7,7 +7,7 @@ use pacquet_diagnostics::{ use pacquet_lockfile::Lockfile; use pacquet_npmrc::Npmrc; use pacquet_package_json::PackageJson; -use pacquet_package_manager::{AutoImportError, CreateVirtdirError}; +use pacquet_package_manager::{AutoImportError, CreateVirtdirError, ImportPackageError}; use pacquet_tarball::Cache; #[derive(Error, Debug, Diagnostic)] @@ -40,6 +40,10 @@ pub enum PackageManagerError { #[error(transparent)] #[diagnostic(transparent)] CreateVirtdir(#[from] CreateVirtdirError), + + #[error(transparent)] + #[diagnostic(transparent)] + ImportPackage(#[from] ImportPackageError), } pub struct PackageManager { diff --git a/crates/package_manager/Cargo.toml b/crates/package_manager/Cargo.toml index 18c331f95..eea0a76f7 100644 --- a/crates/package_manager/Cargo.toml +++ b/crates/package_manager/Cargo.toml @@ -18,4 +18,5 @@ pacquet_npmrc = { workspace = true } derive_more = { workspace = true } rayon = { workspace = true } reflink-copy = { workspace = true } +tracing = { workspace = true } miette = { workspace = true } diff --git a/crates/package_manager/src/import_pkg.rs b/crates/package_manager/src/import_pkg.rs index 04af047a0..aa598754b 100644 --- a/crates/package_manager/src/import_pkg.rs +++ b/crates/package_manager/src/import_pkg.rs @@ -1,10 +1,78 @@ use derive_more::{Display, Error}; use miette::Diagnostic; +use pacquet_fs::symlink_dir; +use pacquet_npmrc::PackageImportMethod; +use rayon::prelude::*; use std::{ + collections::HashMap, + ffi::OsString, fs, io, path::{Path, PathBuf}, }; +#[derive(Debug, Display, Error, Diagnostic)] +pub enum ImportPackageError { + #[display(fmt = "cannot create parent dir for {symlink_path:?}: {error}")] + CreateParentDir { + symlink_path: PathBuf, + #[error(source)] + error: io::Error, + }, + #[display(fmt = "cannot create symlink at {symlink_path:?}: {error}")] + SymlinkDir { + symlink_path: PathBuf, + #[error(source)] + error: io::Error, + }, +} + +pub struct ImportPackage<'a> { + pub method: PackageImportMethod, + pub cas_paths: &'a HashMap, + pub save_path: &'a Path, + pub symlink_path: &'a Path, +} + +impl<'a> ImportPackage<'a> { + pub fn import_pkg(self) -> Result<(), ImportPackageError> { + let ImportPackage { method, cas_paths, save_path, symlink_path } = self; + + tracing::info!(target: "pacquet::import", ?save_path, ?symlink_path, "Import package"); + match method { + PackageImportMethod::Auto => { + if !save_path.exists() { + cas_paths + .into_par_iter() + .try_for_each(|(cleaned_entry, store_path)| { + auto_import(store_path, &save_path.join(cleaned_entry)) + }) + .expect("expected no write errors"); + } + + if !symlink_path.is_symlink() { + if let Some(parent_dir) = symlink_path.parent() { + fs::create_dir_all(parent_dir).map_err(|error| { + ImportPackageError::CreateParentDir { + symlink_path: symlink_path.to_path_buf(), + error, + } + })?; + } + symlink_dir(save_path, symlink_path).map_err(|error| { + ImportPackageError::SymlinkDir { + symlink_path: symlink_path.to_path_buf(), + error, + } + })?; + } + } + _ => panic!("Not implemented yet"), + } + + Ok(()) + } +} + #[derive(Debug, Display, Error, Diagnostic)] pub enum AutoImportError { #[display(fmt = "cannot create directory at {dirname:?}: {error}")] diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index 84e54f705..cfa2a3150 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -2,6 +2,6 @@ mod import_pkg; mod symlink_pkg; mod virtual_dir; -pub use import_pkg::{auto_import, AutoImportError}; +pub use import_pkg::{auto_import, AutoImportError, ImportPackage, ImportPackageError}; pub use symlink_pkg::symlink_pkg; pub use virtual_dir::{create_virtdir_by_snapshot, CreateVirtdirError}; From 4db8e06301dac637a5c2c593c1ce66952f05f5f8 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 6 Oct 2023 23:03:47 +0700 Subject: [PATCH 008/210] refactor: remove unused enum variant --- crates/cli/src/package_manager.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/crates/cli/src/package_manager.rs b/crates/cli/src/package_manager.rs index f88705042..893a7bab5 100644 --- a/crates/cli/src/package_manager.rs +++ b/crates/cli/src/package_manager.rs @@ -7,7 +7,7 @@ use pacquet_diagnostics::{ use pacquet_lockfile::Lockfile; use pacquet_npmrc::Npmrc; use pacquet_package_json::PackageJson; -use pacquet_package_manager::{AutoImportError, CreateVirtdirError, ImportPackageError}; +use pacquet_package_manager::{CreateVirtdirError, ImportPackageError}; use pacquet_tarball::Cache; #[derive(Error, Debug, Diagnostic)] @@ -33,10 +33,6 @@ pub enum PackageManagerError { #[diagnostic(code(pacquet_package_manager::io_error))] Io(#[from] io::Error), - #[error(transparent)] - #[diagnostic(transparent)] - AutoImport(#[from] AutoImportError), - #[error(transparent)] #[diagnostic(transparent)] CreateVirtdir(#[from] CreateVirtdirError), From a58343c2064409d2f78ac6f4b2df4b82f54b8829 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 6 Oct 2023 23:10:02 +0700 Subject: [PATCH 009/210] refactor: use better names --- crates/package_manager/src/import_pkg.rs | 10 +++++----- crates/package_manager/src/lib.rs | 2 +- crates/package_manager/src/virtual_dir.rs | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/crates/package_manager/src/import_pkg.rs b/crates/package_manager/src/import_pkg.rs index aa598754b..b10f95f3b 100644 --- a/crates/package_manager/src/import_pkg.rs +++ b/crates/package_manager/src/import_pkg.rs @@ -44,7 +44,7 @@ impl<'a> ImportPackage<'a> { cas_paths .into_par_iter() .try_for_each(|(cleaned_entry, store_path)| { - auto_import(store_path, &save_path.join(cleaned_entry)) + link_file(store_path, &save_path.join(cleaned_entry)) }) .expect("expected no write errors"); } @@ -74,7 +74,7 @@ impl<'a> ImportPackage<'a> { } #[derive(Debug, Display, Error, Diagnostic)] -pub enum AutoImportError { +pub enum LinkFileError { #[display(fmt = "cannot create directory at {dirname:?}: {error}")] CreateDir { dirname: PathBuf, @@ -90,20 +90,20 @@ pub enum AutoImportError { }, } -pub fn auto_import(source_file: &Path, target_link: &Path) -> Result<(), AutoImportError> { +pub fn link_file(source_file: &Path, target_link: &Path) -> Result<(), LinkFileError> { if target_link.exists() { return Ok(()); } if let Some(parent_dir) = target_link.parent() { - fs::create_dir_all(parent_dir).map_err(|error| AutoImportError::CreateDir { + fs::create_dir_all(parent_dir).map_err(|error| LinkFileError::CreateDir { dirname: parent_dir.to_path_buf(), error, })?; } reflink_copy::reflink_or_copy(source_file, target_link).map_err(|error| { - AutoImportError::CreateLink { + LinkFileError::CreateLink { from: source_file.to_path_buf(), to: target_link.to_path_buf(), error, diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index cfa2a3150..4996173e8 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -2,6 +2,6 @@ mod import_pkg; mod symlink_pkg; mod virtual_dir; -pub use import_pkg::{auto_import, AutoImportError, ImportPackage, ImportPackageError}; +pub use import_pkg::{link_file, ImportPackage, ImportPackageError, LinkFileError}; pub use symlink_pkg::symlink_pkg; pub use virtual_dir::{create_virtdir_by_snapshot, CreateVirtdirError}; diff --git a/crates/package_manager/src/virtual_dir.rs b/crates/package_manager/src/virtual_dir.rs index e438a6f7e..7498ba727 100644 --- a/crates/package_manager/src/virtual_dir.rs +++ b/crates/package_manager/src/virtual_dir.rs @@ -1,4 +1,4 @@ -use crate::{auto_import, symlink_pkg, AutoImportError}; +use crate::{link_file, symlink_pkg, LinkFileError}; use derive_more::{Display, Error}; use miette::Diagnostic; use pacquet_lockfile::{ @@ -16,7 +16,7 @@ use std::{ #[derive(Debug, Display, Error, Diagnostic)] pub enum CreateVirtdirError { #[diagnostic(transparent)] - AutoImport(#[error(source)] AutoImportError), + LinkFile(#[error(source)] LinkFileError), } /// This function does 2 things: @@ -50,8 +50,8 @@ pub fn create_virtdir_by_snapshot( virtual_node_modules_dir.join(dependency_path.package_specifier.name.to_string()); if !save_path.exists() { cas_paths.par_iter().try_for_each(|(cleaned_entry, store_path)| { - auto_import(store_path, &save_path.join(cleaned_entry)) - .map_err(CreateVirtdirError::AutoImport) + link_file(store_path, &save_path.join(cleaned_entry)) + .map_err(CreateVirtdirError::LinkFile) })?; } From 92e9eea28a281082eb77727786a8d60b73f81ca8 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 6 Oct 2023 23:10:42 +0700 Subject: [PATCH 010/210] docs: link_file --- crates/package_manager/src/import_pkg.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/package_manager/src/import_pkg.rs b/crates/package_manager/src/import_pkg.rs index b10f95f3b..c91be03e6 100644 --- a/crates/package_manager/src/import_pkg.rs +++ b/crates/package_manager/src/import_pkg.rs @@ -73,6 +73,7 @@ impl<'a> ImportPackage<'a> { } } +/// Error type for [`link_file`]. #[derive(Debug, Display, Error, Diagnostic)] pub enum LinkFileError { #[display(fmt = "cannot create directory at {dirname:?}: {error}")] @@ -90,6 +91,9 @@ pub enum LinkFileError { }, } +/// Reflink or copy a single file. +/// +/// If parent dir of `target_link` doesn't exist, it will be created. pub fn link_file(source_file: &Path, target_link: &Path) -> Result<(), LinkFileError> { if target_link.exists() { return Ok(()); From 207a87d566547446eaa2c8bdb9dedcb46920bc00 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 6 Oct 2023 23:12:56 +0700 Subject: [PATCH 011/210] refactor: move link_file to its own mod --- crates/package_manager/src/import_pkg.rs | 45 +-------------------- crates/package_manager/src/lib.rs | 4 +- crates/package_manager/src/link_file.rs | 50 ++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 45 deletions(-) create mode 100644 crates/package_manager/src/link_file.rs diff --git a/crates/package_manager/src/import_pkg.rs b/crates/package_manager/src/import_pkg.rs index c91be03e6..09d5c60e9 100644 --- a/crates/package_manager/src/import_pkg.rs +++ b/crates/package_manager/src/import_pkg.rs @@ -1,3 +1,4 @@ +use crate::link_file; use derive_more::{Display, Error}; use miette::Diagnostic; use pacquet_fs::symlink_dir; @@ -72,47 +73,3 @@ impl<'a> ImportPackage<'a> { Ok(()) } } - -/// Error type for [`link_file`]. -#[derive(Debug, Display, Error, Diagnostic)] -pub enum LinkFileError { - #[display(fmt = "cannot create directory at {dirname:?}: {error}")] - CreateDir { - dirname: PathBuf, - #[error(source)] - error: io::Error, - }, - #[display(fmt = "fail to create a link from {from:?} to {to:?}: {error}")] - CreateLink { - from: PathBuf, - to: PathBuf, - #[error(source)] - error: io::Error, - }, -} - -/// Reflink or copy a single file. -/// -/// If parent dir of `target_link` doesn't exist, it will be created. -pub fn link_file(source_file: &Path, target_link: &Path) -> Result<(), LinkFileError> { - if target_link.exists() { - return Ok(()); - } - - if let Some(parent_dir) = target_link.parent() { - fs::create_dir_all(parent_dir).map_err(|error| LinkFileError::CreateDir { - dirname: parent_dir.to_path_buf(), - error, - })?; - } - - reflink_copy::reflink_or_copy(source_file, target_link).map_err(|error| { - LinkFileError::CreateLink { - from: source_file.to_path_buf(), - to: target_link.to_path_buf(), - error, - } - })?; // TODO: add hardlink - - Ok(()) -} diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index 4996173e8..bec2c9b34 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -1,7 +1,9 @@ mod import_pkg; +mod link_file; mod symlink_pkg; mod virtual_dir; -pub use import_pkg::{link_file, ImportPackage, ImportPackageError, LinkFileError}; +pub use import_pkg::{ImportPackage, ImportPackageError}; +pub use link_file::{link_file, LinkFileError}; pub use symlink_pkg::symlink_pkg; pub use virtual_dir::{create_virtdir_by_snapshot, CreateVirtdirError}; diff --git a/crates/package_manager/src/link_file.rs b/crates/package_manager/src/link_file.rs new file mode 100644 index 000000000..7de40c21e --- /dev/null +++ b/crates/package_manager/src/link_file.rs @@ -0,0 +1,50 @@ +use derive_more::{Display, Error}; +use miette::Diagnostic; +use std::{ + fs, io, + path::{Path, PathBuf}, +}; + +/// Error type for [`link_file`]. +#[derive(Debug, Display, Error, Diagnostic)] +pub enum LinkFileError { + #[display(fmt = "cannot create directory at {dirname:?}: {error}")] + CreateDir { + dirname: PathBuf, + #[error(source)] + error: io::Error, + }, + #[display(fmt = "fail to create a link from {from:?} to {to:?}: {error}")] + CreateLink { + from: PathBuf, + to: PathBuf, + #[error(source)] + error: io::Error, + }, +} + +/// Reflink or copy a single file. +/// +/// If parent dir of `target_link` doesn't exist, it will be created. +pub fn link_file(source_file: &Path, target_link: &Path) -> Result<(), LinkFileError> { + if target_link.exists() { + return Ok(()); + } + + if let Some(parent_dir) = target_link.parent() { + fs::create_dir_all(parent_dir).map_err(|error| LinkFileError::CreateDir { + dirname: parent_dir.to_path_buf(), + error, + })?; + } + + reflink_copy::reflink_or_copy(source_file, target_link).map_err(|error| { + LinkFileError::CreateLink { + from: source_file.to_path_buf(), + to: target_link.to_path_buf(), + error, + } + })?; // TODO: add hardlink + + Ok(()) +} From 5155f95f44d28952a416dcda0da8d62cc83ae7d8 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 6 Oct 2023 23:17:12 +0700 Subject: [PATCH 012/210] docs: correction --- crates/package_manager/src/link_file.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/package_manager/src/link_file.rs b/crates/package_manager/src/link_file.rs index 7de40c21e..229cfb569 100644 --- a/crates/package_manager/src/link_file.rs +++ b/crates/package_manager/src/link_file.rs @@ -25,7 +25,8 @@ pub enum LinkFileError { /// Reflink or copy a single file. /// -/// If parent dir of `target_link` doesn't exist, it will be created. +/// * If `target_link` already exists, do nothing. +/// * If parent dir of `target_link` doesn't exist, it will be created. pub fn link_file(source_file: &Path, target_link: &Path) -> Result<(), LinkFileError> { if target_link.exists() { return Ok(()); From f2e8f45cf96634adcede43238b082ff6a896caa8 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 9 Oct 2023 13:32:29 +0700 Subject: [PATCH 013/210] chore(cargo): move junction to dev-dependencies --- crates/cli/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index d1cffe69e..ada14984a 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -31,7 +31,6 @@ clap = { workspace = true } futures-util = { workspace = true } rayon = { workspace = true } reflink-copy = { workspace = true } -junction = { workspace = true } reqwest = { workspace = true } node-semver = { workspace = true } pipe-trait = { workspace = true } @@ -41,6 +40,7 @@ tokio = { workspace = true } [dev-dependencies] insta = { workspace = true } +junction = { workspace = true } pretty_assertions = { workspace = true } tempfile = { workspace = true } walkdir = { workspace = true } From 8b00c83bee5223d2436709879b7758eceae0d868 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 9 Oct 2023 13:35:42 +0700 Subject: [PATCH 014/210] chore(cargo): make `junction` windows-only --- crates/cli/Cargo.toml | 4 +++- crates/fs/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index ada14984a..1e09125b9 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -40,7 +40,9 @@ tokio = { workspace = true } [dev-dependencies] insta = { workspace = true } -junction = { workspace = true } pretty_assertions = { workspace = true } tempfile = { workspace = true } walkdir = { workspace = true } + +[target.'cfg(windows)'.dev-dependencies] +junction = { workspace = true } diff --git a/crates/fs/Cargo.toml b/crates/fs/Cargo.toml index dbfb6d9d5..eba300d13 100644 --- a/crates/fs/Cargo.toml +++ b/crates/fs/Cargo.toml @@ -10,5 +10,5 @@ keywords.workspace = true license.workspace = true repository.workspace = true -[dependencies] +[target.'cfg(windows)'.dependencies] junction = { workspace = true } From abfaddbc0c396dc35c2e2a9d359c2b671b88d02f Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 9 Oct 2023 14:39:39 +0700 Subject: [PATCH 015/210] refactor: rename --- crates/cli/src/package.rs | 4 ++-- crates/cli/src/package_manager.rs | 4 ++-- crates/package_manager/src/lib.rs | 2 +- crates/package_manager/src/virtual_dir.rs | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/cli/src/package.rs b/crates/cli/src/package.rs index 7d0e73121..90ac2a370 100644 --- a/crates/cli/src/package.rs +++ b/crates/cli/src/package.rs @@ -1,7 +1,7 @@ use crate::package_manager::PackageManagerError; use pacquet_lockfile::{DependencyPath, LockfileResolution, PackageSnapshot, PkgNameVerPeer}; use pacquet_npmrc::Npmrc; -use pacquet_package_manager::create_virtdir_by_snapshot; +use pacquet_package_manager::create_virtual_dir_by_snapshot; use pacquet_package_manager::ImportPackage; use pacquet_registry::{Package, PackageVersion}; use pacquet_tarball::{download_tarball_to_store, Cache}; @@ -126,7 +126,7 @@ pub async fn install_single_package_to_virtual_store( ) .await?; - create_virtdir_by_snapshot( + create_virtual_dir_by_snapshot( dependency_path, &config.virtual_store_dir, &cas_paths, diff --git a/crates/cli/src/package_manager.rs b/crates/cli/src/package_manager.rs index 893a7bab5..9b43ede57 100644 --- a/crates/cli/src/package_manager.rs +++ b/crates/cli/src/package_manager.rs @@ -7,7 +7,7 @@ use pacquet_diagnostics::{ use pacquet_lockfile::Lockfile; use pacquet_npmrc::Npmrc; use pacquet_package_json::PackageJson; -use pacquet_package_manager::{CreateVirtdirError, ImportPackageError}; +use pacquet_package_manager::{CreateVirtualDirError, ImportPackageError}; use pacquet_tarball::Cache; #[derive(Error, Debug, Diagnostic)] @@ -35,7 +35,7 @@ pub enum PackageManagerError { #[error(transparent)] #[diagnostic(transparent)] - CreateVirtdir(#[from] CreateVirtdirError), + CreateVirtdir(#[from] CreateVirtualDirError), #[error(transparent)] #[diagnostic(transparent)] diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index bec2c9b34..8aa127107 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -6,4 +6,4 @@ mod virtual_dir; pub use import_pkg::{ImportPackage, ImportPackageError}; pub use link_file::{link_file, LinkFileError}; pub use symlink_pkg::symlink_pkg; -pub use virtual_dir::{create_virtdir_by_snapshot, CreateVirtdirError}; +pub use virtual_dir::{create_virtual_dir_by_snapshot, CreateVirtualDirError}; diff --git a/crates/package_manager/src/virtual_dir.rs b/crates/package_manager/src/virtual_dir.rs index 7498ba727..6d5b0bc1c 100644 --- a/crates/package_manager/src/virtual_dir.rs +++ b/crates/package_manager/src/virtual_dir.rs @@ -14,7 +14,7 @@ use std::{ }; #[derive(Debug, Display, Error, Diagnostic)] -pub enum CreateVirtdirError { +pub enum CreateVirtualDirError { #[diagnostic(transparent)] LinkFile(#[error(source)] LinkFileError), } @@ -24,13 +24,13 @@ pub enum CreateVirtdirError { /// 2. Create the symlink layout /// /// **TODO:** may break this function into 2 later -pub fn create_virtdir_by_snapshot( +pub fn create_virtual_dir_by_snapshot( dependency_path: &DependencyPath, virtual_store_dir: &Path, cas_paths: &HashMap, import_method: PackageImportMethod, package_snapshot: &PackageSnapshot, -) -> Result<(), CreateVirtdirError> { +) -> Result<(), CreateVirtualDirError> { assert_eq!( import_method, PackageImportMethod::Auto, @@ -51,7 +51,7 @@ pub fn create_virtdir_by_snapshot( if !save_path.exists() { cas_paths.par_iter().try_for_each(|(cleaned_entry, store_path)| { link_file(store_path, &save_path.join(cleaned_entry)) - .map_err(CreateVirtdirError::LinkFile) + .map_err(CreateVirtualDirError::LinkFile) })?; } From 61f00d30518952af4b3c4e61101c5772c38addb7 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 9 Oct 2023 16:01:50 +0700 Subject: [PATCH 016/210] refactor: break a function into 2 --- crates/package_manager/src/cas.rs | 35 ++++++++++++++++++++ crates/package_manager/src/lib.rs | 4 +++ crates/package_manager/src/symlink_layout.rs | 30 +++++++++++++++++ crates/package_manager/src/virtual_dir.rs | 35 +++----------------- 4 files changed, 74 insertions(+), 30 deletions(-) create mode 100644 crates/package_manager/src/cas.rs create mode 100644 crates/package_manager/src/symlink_layout.rs diff --git a/crates/package_manager/src/cas.rs b/crates/package_manager/src/cas.rs new file mode 100644 index 000000000..4b90bd39f --- /dev/null +++ b/crates/package_manager/src/cas.rs @@ -0,0 +1,35 @@ +use crate::{link_file, LinkFileError}; +use derive_more::{Display, Error}; +use miette::Diagnostic; +use rayon::prelude::*; +use std::{ + collections::HashMap, + ffi::OsString, + path::{Path, PathBuf}, +}; + +/// Error type for [`create_cas_files`]. +#[derive(Debug, Display, Error, Diagnostic)] +pub enum CreateCasFilesError { + #[diagnostic(transparent)] + LinkFile(#[error(source)] LinkFileError), +} + +/// If `dir_path` doesn't exist, create and populate it with files from `cas_paths`. +/// +/// If `dir_path` already exists, do nothing. +pub fn create_cas_files( + dir_path: &Path, + cas_paths: &HashMap, +) -> Result<(), CreateCasFilesError> { + if dir_path.exists() { + return Ok(()); + } + + cas_paths + .par_iter() + .try_for_each(|(cleaned_entry, store_path)| { + link_file(store_path, &dir_path.join(cleaned_entry)) + }) + .map_err(CreateCasFilesError::LinkFile) +} diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index 8aa127107..8ea837ae6 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -1,9 +1,13 @@ +mod cas; mod import_pkg; mod link_file; +mod symlink_layout; mod symlink_pkg; mod virtual_dir; +pub use cas::{create_cas_files, CreateCasFilesError}; pub use import_pkg::{ImportPackage, ImportPackageError}; pub use link_file::{link_file, LinkFileError}; +pub use symlink_layout::create_symlink_layout; pub use symlink_pkg::symlink_pkg; pub use virtual_dir::{create_virtual_dir_by_snapshot, CreateVirtualDirError}; diff --git a/crates/package_manager/src/symlink_layout.rs b/crates/package_manager/src/symlink_layout.rs new file mode 100644 index 000000000..3dfb5939f --- /dev/null +++ b/crates/package_manager/src/symlink_layout.rs @@ -0,0 +1,30 @@ +use crate::symlink_pkg; +use pacquet_lockfile::{PackageSnapshotDependency, PkgName, PkgNameVerPeer}; +use rayon::prelude::*; +use std::{collections::HashMap, path::Path}; + +/// Create symlink layout of dependencies for a package in a virtual dir. +/// +/// **NOTE:** `virtual_node_modules_dir` is assumed to already exist. +pub fn create_symlink_layout( + dependencies: &HashMap, + virtual_root: &Path, + virtual_node_modules_dir: &Path, +) { + dependencies.par_iter().for_each(|(name, spec)| { + let virtual_store_name = match spec { + PackageSnapshotDependency::PkgVerPeer(ver_peer) => { + let package_specifier = PkgNameVerPeer::new(name.clone(), ver_peer.clone()); // TODO: remove copying here + package_specifier.to_virtual_store_name() + } + PackageSnapshotDependency::DependencyPath(dependency_path) => { + dependency_path.package_specifier.to_virtual_store_name() + } + }; + let name_str = name.to_string(); + symlink_pkg( + &virtual_root.join(virtual_store_name).join("node_modules").join(&name_str), + &virtual_node_modules_dir.join(&name_str), + ); + }); +} diff --git a/crates/package_manager/src/virtual_dir.rs b/crates/package_manager/src/virtual_dir.rs index 6d5b0bc1c..959c67593 100644 --- a/crates/package_manager/src/virtual_dir.rs +++ b/crates/package_manager/src/virtual_dir.rs @@ -1,11 +1,8 @@ -use crate::{link_file, symlink_pkg, LinkFileError}; +use crate::{create_cas_files, create_symlink_layout, CreateCasFilesError}; use derive_more::{Display, Error}; use miette::Diagnostic; -use pacquet_lockfile::{ - DependencyPath, PackageSnapshot, PackageSnapshotDependency, PkgNameVerPeer, -}; +use pacquet_lockfile::{DependencyPath, PackageSnapshot}; use pacquet_npmrc::PackageImportMethod; -use rayon::prelude::*; use std::{ collections::HashMap, ffi::OsString, @@ -16,14 +13,12 @@ use std::{ #[derive(Debug, Display, Error, Diagnostic)] pub enum CreateVirtualDirError { #[diagnostic(transparent)] - LinkFile(#[error(source)] LinkFileError), + CreateCasFiles(#[error(source)] CreateCasFilesError), } /// This function does 2 things: /// 1. Install the files from `cas_paths` /// 2. Create the symlink layout -/// -/// **TODO:** may break this function into 2 later pub fn create_virtual_dir_by_snapshot( dependency_path: &DependencyPath, virtual_store_dir: &Path, @@ -48,31 +43,11 @@ pub fn create_virtual_dir_by_snapshot( // 1. Install the files from `cas_paths` let save_path = virtual_node_modules_dir.join(dependency_path.package_specifier.name.to_string()); - if !save_path.exists() { - cas_paths.par_iter().try_for_each(|(cleaned_entry, store_path)| { - link_file(store_path, &save_path.join(cleaned_entry)) - .map_err(CreateVirtualDirError::LinkFile) - })?; - } + create_cas_files(&save_path, cas_paths).map_err(CreateVirtualDirError::CreateCasFiles)?; // 2. Create the symlink layout if let Some(dependencies) = &package_snapshot.dependencies { - dependencies.par_iter().for_each(|(name, spec)| { - let virtual_store_name = match spec { - PackageSnapshotDependency::PkgVerPeer(ver_peer) => { - let package_specifier = PkgNameVerPeer::new(name.clone(), ver_peer.clone()); // TODO: remove copying here - package_specifier.to_virtual_store_name() - } - PackageSnapshotDependency::DependencyPath(dependency_path) => { - dependency_path.package_specifier.to_virtual_store_name() - } - }; - let name_str = name.to_string(); - symlink_pkg( - &virtual_store_dir.join(virtual_store_name).join("node_modules").join(&name_str), - &virtual_node_modules_dir.join(&name_str), - ); - }); + create_symlink_layout(dependencies, virtual_store_dir, &virtual_node_modules_dir) } Ok(()) From a6cdcf5f2d6d1b10ab59f198eaa814f08c181858 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 9 Oct 2023 17:52:15 +0700 Subject: [PATCH 017/210] feat: propagate an error --- crates/package_manager/src/virtual_dir.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/crates/package_manager/src/virtual_dir.rs b/crates/package_manager/src/virtual_dir.rs index 959c67593..dffc84634 100644 --- a/crates/package_manager/src/virtual_dir.rs +++ b/crates/package_manager/src/virtual_dir.rs @@ -6,12 +6,20 @@ use pacquet_npmrc::PackageImportMethod; use std::{ collections::HashMap, ffi::OsString, - fs, + fs, io, path::{Path, PathBuf}, }; #[derive(Debug, Display, Error, Diagnostic)] pub enum CreateVirtualDirError { + #[display(fmt = "Failed to recursively create node_modules directory at {dir:?}: {error}")] + #[diagnostic(code(pacquet_package_manager::create_node_modules_dir))] + CreateNodeModulesDir { + dir: PathBuf, + #[error(source)] + error: io::Error, + }, + #[diagnostic(transparent)] CreateCasFiles(#[error(source)] CreateCasFilesError), } @@ -36,9 +44,12 @@ pub fn create_virtual_dir_by_snapshot( let virtual_node_modules_dir = virtual_store_dir .join(dependency_path.package_specifier.to_virtual_store_name()) .join("node_modules"); - fs::create_dir_all(&virtual_node_modules_dir).unwrap_or_else(|error| { - panic!("Failed to create directory at {virtual_node_modules_dir:?}: {error}") - }); // TODO: proper error propagation + fs::create_dir_all(&virtual_node_modules_dir).map_err(|error| { + CreateVirtualDirError::CreateNodeModulesDir { + dir: virtual_node_modules_dir.to_path_buf(), + error, + } + })?; // 1. Install the files from `cas_paths` let save_path = From 673c0d85bec3cef096b612acc474db0c809909b8 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 9 Oct 2023 18:01:16 +0700 Subject: [PATCH 018/210] refactor: convert a function into a struct --- crates/cli/src/package.rs | 13 ++-- crates/package_manager/src/lib.rs | 2 +- crates/package_manager/src/virtual_dir.rs | 77 +++++++++++++---------- 3 files changed, 53 insertions(+), 39 deletions(-) diff --git a/crates/cli/src/package.rs b/crates/cli/src/package.rs index 90ac2a370..8a95ba8bb 100644 --- a/crates/cli/src/package.rs +++ b/crates/cli/src/package.rs @@ -1,7 +1,7 @@ use crate::package_manager::PackageManagerError; use pacquet_lockfile::{DependencyPath, LockfileResolution, PackageSnapshot, PkgNameVerPeer}; use pacquet_npmrc::Npmrc; -use pacquet_package_manager::create_virtual_dir_by_snapshot; +use pacquet_package_manager::CreateVirtualDirBySnapshot; use pacquet_package_manager::ImportPackage; use pacquet_registry::{Package, PackageVersion}; use pacquet_tarball::{download_tarball_to_store, Cache}; @@ -126,13 +126,14 @@ pub async fn install_single_package_to_virtual_store( ) .await?; - create_virtual_dir_by_snapshot( + CreateVirtualDirBySnapshot { dependency_path, - &config.virtual_store_dir, - &cas_paths, - config.package_import_method, + virtual_store_dir: &config.virtual_store_dir, + cas_paths: &cas_paths, + import_method: config.package_import_method, package_snapshot, - )?; + } + .create_virtual_dir_by_snapshot()?; Ok(()) } diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index 8ea837ae6..bd67de594 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -10,4 +10,4 @@ pub use import_pkg::{ImportPackage, ImportPackageError}; pub use link_file::{link_file, LinkFileError}; pub use symlink_layout::create_symlink_layout; pub use symlink_pkg::symlink_pkg; -pub use virtual_dir::{create_virtual_dir_by_snapshot, CreateVirtualDirError}; +pub use virtual_dir::{CreateVirtualDirBySnapshot, CreateVirtualDirError}; diff --git a/crates/package_manager/src/virtual_dir.rs b/crates/package_manager/src/virtual_dir.rs index dffc84634..8d8d17cba 100644 --- a/crates/package_manager/src/virtual_dir.rs +++ b/crates/package_manager/src/virtual_dir.rs @@ -24,42 +24,55 @@ pub enum CreateVirtualDirError { CreateCasFiles(#[error(source)] CreateCasFilesError), } -/// This function does 2 things: +/// This subroutine does 2 things: /// 1. Install the files from `cas_paths` /// 2. Create the symlink layout -pub fn create_virtual_dir_by_snapshot( - dependency_path: &DependencyPath, - virtual_store_dir: &Path, - cas_paths: &HashMap, - import_method: PackageImportMethod, - package_snapshot: &PackageSnapshot, -) -> Result<(), CreateVirtualDirError> { - assert_eq!( - import_method, - PackageImportMethod::Auto, - "Only auto import method is supported, but {dependency_path} requires {import_method:?}", - ); +pub struct CreateVirtualDirBySnapshot<'a> { + pub dependency_path: &'a DependencyPath, + pub virtual_store_dir: &'a Path, + pub cas_paths: &'a HashMap, + pub import_method: PackageImportMethod, + pub package_snapshot: &'a PackageSnapshot, +} - // node_modules/.pacquet/pkg-name@x.y.z/node_modules - let virtual_node_modules_dir = virtual_store_dir - .join(dependency_path.package_specifier.to_virtual_store_name()) - .join("node_modules"); - fs::create_dir_all(&virtual_node_modules_dir).map_err(|error| { - CreateVirtualDirError::CreateNodeModulesDir { - dir: virtual_node_modules_dir.to_path_buf(), - error, - } - })?; +impl<'a> CreateVirtualDirBySnapshot<'a> { + /// Execute the subroutine. + pub fn create_virtual_dir_by_snapshot(self) -> Result<(), CreateVirtualDirError> { + let CreateVirtualDirBySnapshot { + dependency_path, + virtual_store_dir, + cas_paths, + import_method, + package_snapshot, + } = self; - // 1. Install the files from `cas_paths` - let save_path = - virtual_node_modules_dir.join(dependency_path.package_specifier.name.to_string()); - create_cas_files(&save_path, cas_paths).map_err(CreateVirtualDirError::CreateCasFiles)?; + assert_eq!( + import_method, + PackageImportMethod::Auto, + "Only auto import method is supported, but {dependency_path} requires {import_method:?}", + ); - // 2. Create the symlink layout - if let Some(dependencies) = &package_snapshot.dependencies { - create_symlink_layout(dependencies, virtual_store_dir, &virtual_node_modules_dir) - } + // node_modules/.pacquet/pkg-name@x.y.z/node_modules + let virtual_node_modules_dir = virtual_store_dir + .join(dependency_path.package_specifier.to_virtual_store_name()) + .join("node_modules"); + fs::create_dir_all(&virtual_node_modules_dir).map_err(|error| { + CreateVirtualDirError::CreateNodeModulesDir { + dir: virtual_node_modules_dir.to_path_buf(), + error, + } + })?; + + // 1. Install the files from `cas_paths` + let save_path = + virtual_node_modules_dir.join(dependency_path.package_specifier.name.to_string()); + create_cas_files(&save_path, cas_paths).map_err(CreateVirtualDirError::CreateCasFiles)?; - Ok(()) + // 2. Create the symlink layout + if let Some(dependencies) = &package_snapshot.dependencies { + create_symlink_layout(dependencies, virtual_store_dir, &virtual_node_modules_dir) + } + + Ok(()) + } } From 03d1f8b92628de4a3930d0df6c5d6f3510180595 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 9 Oct 2023 18:01:54 +0700 Subject: [PATCH 019/210] docs: CreateVirtualDirError --- crates/package_manager/src/virtual_dir.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/package_manager/src/virtual_dir.rs b/crates/package_manager/src/virtual_dir.rs index 8d8d17cba..ca4e9bb9e 100644 --- a/crates/package_manager/src/virtual_dir.rs +++ b/crates/package_manager/src/virtual_dir.rs @@ -10,6 +10,7 @@ use std::{ path::{Path, PathBuf}, }; +/// Error type of [`CreateVirtualDirBySnapshot`]. #[derive(Debug, Display, Error, Diagnostic)] pub enum CreateVirtualDirError { #[display(fmt = "Failed to recursively create node_modules directory at {dir:?}: {error}")] From f63a4293391dc70e52a03dec7b6ade1c3d5aa8ff Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 9 Oct 2023 18:02:34 +0700 Subject: [PATCH 020/210] style: mark procedure structs as `must_use` --- crates/package_manager/src/import_pkg.rs | 1 + crates/package_manager/src/virtual_dir.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/crates/package_manager/src/import_pkg.rs b/crates/package_manager/src/import_pkg.rs index 09d5c60e9..3350da0d5 100644 --- a/crates/package_manager/src/import_pkg.rs +++ b/crates/package_manager/src/import_pkg.rs @@ -27,6 +27,7 @@ pub enum ImportPackageError { }, } +#[must_use] pub struct ImportPackage<'a> { pub method: PackageImportMethod, pub cas_paths: &'a HashMap, diff --git a/crates/package_manager/src/virtual_dir.rs b/crates/package_manager/src/virtual_dir.rs index ca4e9bb9e..13bd2deef 100644 --- a/crates/package_manager/src/virtual_dir.rs +++ b/crates/package_manager/src/virtual_dir.rs @@ -28,6 +28,7 @@ pub enum CreateVirtualDirError { /// This subroutine does 2 things: /// 1. Install the files from `cas_paths` /// 2. Create the symlink layout +#[must_use] pub struct CreateVirtualDirBySnapshot<'a> { pub dependency_path: &'a DependencyPath, pub virtual_store_dir: &'a Path, From 0fc16039fbb82dfa7d739abc8433a52fe313bda4 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 9 Oct 2023 20:17:21 +0700 Subject: [PATCH 021/210] refactor: reuse create_cas_files in ImportPackage --- crates/package_manager/src/import_pkg.rs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/crates/package_manager/src/import_pkg.rs b/crates/package_manager/src/import_pkg.rs index 3350da0d5..89c44b815 100644 --- a/crates/package_manager/src/import_pkg.rs +++ b/crates/package_manager/src/import_pkg.rs @@ -1,9 +1,8 @@ -use crate::link_file; +use crate::create_cas_files; use derive_more::{Display, Error}; use miette::Diagnostic; use pacquet_fs::symlink_dir; use pacquet_npmrc::PackageImportMethod; -use rayon::prelude::*; use std::{ collections::HashMap, ffi::OsString, @@ -42,14 +41,7 @@ impl<'a> ImportPackage<'a> { tracing::info!(target: "pacquet::import", ?save_path, ?symlink_path, "Import package"); match method { PackageImportMethod::Auto => { - if !save_path.exists() { - cas_paths - .into_par_iter() - .try_for_each(|(cleaned_entry, store_path)| { - link_file(store_path, &save_path.join(cleaned_entry)) - }) - .expect("expected no write errors"); - } + create_cas_files(save_path, cas_paths).expect("no write errors"); // TODO: properly propagate the error if !symlink_path.is_symlink() { if let Some(parent_dir) = symlink_path.parent() { From 5890ab1e447a0870dbed3e3cf5b4568226410ccb Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 9 Oct 2023 20:25:55 +0700 Subject: [PATCH 022/210] docs: ImportPackage --- crates/package_manager/src/import_pkg.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/package_manager/src/import_pkg.rs b/crates/package_manager/src/import_pkg.rs index 89c44b815..12b2bc27d 100644 --- a/crates/package_manager/src/import_pkg.rs +++ b/crates/package_manager/src/import_pkg.rs @@ -26,6 +26,9 @@ pub enum ImportPackageError { }, } +/// This subroutine does 2 things: +/// 1. Populate files into [`save_path`](Self::save_path) according to [`cas_paths`](Self::cas_paths) and [`method`](Self::method). +/// 2. Create at [`symlink_path`](Self::symlink_path) which points to [`save_path`](Self::save_path). #[must_use] pub struct ImportPackage<'a> { pub method: PackageImportMethod, From f70a8a0bc02e93fa520721d3af0139e7ea783efa Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 9 Oct 2023 20:41:50 +0700 Subject: [PATCH 023/210] feat: SymlinkPackageError --- crates/package_manager/src/lib.rs | 2 +- crates/package_manager/src/symlink_layout.rs | 3 +- crates/package_manager/src/symlink_pkg.rs | 45 +++++++++++++++++--- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index bd67de594..9621d1ec2 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -9,5 +9,5 @@ pub use cas::{create_cas_files, CreateCasFilesError}; pub use import_pkg::{ImportPackage, ImportPackageError}; pub use link_file::{link_file, LinkFileError}; pub use symlink_layout::create_symlink_layout; -pub use symlink_pkg::symlink_pkg; +pub use symlink_pkg::{symlink_pkg, SymlinkPackageError}; pub use virtual_dir::{CreateVirtualDirBySnapshot, CreateVirtualDirError}; diff --git a/crates/package_manager/src/symlink_layout.rs b/crates/package_manager/src/symlink_layout.rs index 3dfb5939f..d9fe56906 100644 --- a/crates/package_manager/src/symlink_layout.rs +++ b/crates/package_manager/src/symlink_layout.rs @@ -25,6 +25,7 @@ pub fn create_symlink_layout( symlink_pkg( &virtual_root.join(virtual_store_name).join("node_modules").join(&name_str), &virtual_node_modules_dir.join(&name_str), - ); + ) + .expect("symlink pkg successful"); // TODO: properly propagate this error }); } diff --git a/crates/package_manager/src/symlink_pkg.rs b/crates/package_manager/src/symlink_pkg.rs index d4b79f7dd..5dc7f23ce 100644 --- a/crates/package_manager/src/symlink_pkg.rs +++ b/crates/package_manager/src/symlink_pkg.rs @@ -1,23 +1,56 @@ +use derive_more::{Display, Error}; +use miette::Diagnostic; use pacquet_fs::symlink_dir; -use std::{fs, io::ErrorKind, path::Path}; +use std::{ + fs, + io::{self, ErrorKind}, + path::{Path, PathBuf}, +}; + +/// Error type for [`symlink_pkg`]. +#[derive(Debug, Display, Error, Diagnostic)] +pub enum SymlinkPackageError { + #[display(fmt = "Failed to create directory at {dir:?}: {error}")] + CreateParentDir { + dir: PathBuf, + #[error(source)] + error: io::Error, + }, + + #[display(fmt = "Failed to create symlink at {symlink_path:?} to {symlink_target:?}: {error}")] + SymlinkDir { + symlink_target: PathBuf, + symlink_path: PathBuf, + #[error(source)] + error: io::Error, + }, +} /// Create symlink for a package. /// /// * If ancestors of `symlink_path` don't exist, they will be created recursively. /// * If `symlink_path` already exists, skip. /// * If `symlink_path` doesn't exist, a symlink pointing to `symlink_target` will be created. -pub fn symlink_pkg(symlink_target: &Path, symlink_path: &Path) { +pub fn symlink_pkg(symlink_target: &Path, symlink_path: &Path) -> Result<(), SymlinkPackageError> { // NOTE: symlink target in pacquet is absolute yet in pnpm is relative // TODO: change symlink target to relative if let Some(parent) = symlink_path.parent() { - fs::create_dir_all(parent).expect("make sure node_modules exist"); // TODO: proper error propagation + fs::create_dir_all(parent).map_err(|error| SymlinkPackageError::CreateParentDir { + dir: parent.to_path_buf(), + error, + })?; } if let Err(error) = symlink_dir(symlink_target, symlink_path) { match error.kind() { ErrorKind::AlreadyExists => {} - _ => panic!( - "Failed to create symlink at {symlink_path:?} to {symlink_target:?}: {error}" - ), // TODO: proper error propagation + _ => { + return Err(SymlinkPackageError::SymlinkDir { + symlink_target: symlink_target.to_path_buf(), + symlink_path: symlink_path.to_path_buf(), + error, + }) + } } } + Ok(()) } From 6080fe46ac6a23a077c7551d1c7e95ebc88989bf Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 9 Oct 2023 20:43:57 +0700 Subject: [PATCH 024/210] refactor: reuse symlink_pkg --- crates/package_manager/src/import_pkg.rs | 31 ++++-------------------- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/crates/package_manager/src/import_pkg.rs b/crates/package_manager/src/import_pkg.rs index 12b2bc27d..d92ad3115 100644 --- a/crates/package_manager/src/import_pkg.rs +++ b/crates/package_manager/src/import_pkg.rs @@ -1,12 +1,11 @@ -use crate::create_cas_files; +use crate::{create_cas_files, symlink_pkg, SymlinkPackageError}; use derive_more::{Display, Error}; use miette::Diagnostic; -use pacquet_fs::symlink_dir; use pacquet_npmrc::PackageImportMethod; use std::{ collections::HashMap, ffi::OsString, - fs, io, + io, path::{Path, PathBuf}, }; @@ -18,12 +17,8 @@ pub enum ImportPackageError { #[error(source)] error: io::Error, }, - #[display(fmt = "cannot create symlink at {symlink_path:?}: {error}")] - SymlinkDir { - symlink_path: PathBuf, - #[error(source)] - error: io::Error, - }, + + SymlinkPackage(SymlinkPackageError), } /// This subroutine does 2 things: @@ -45,23 +40,7 @@ impl<'a> ImportPackage<'a> { match method { PackageImportMethod::Auto => { create_cas_files(save_path, cas_paths).expect("no write errors"); // TODO: properly propagate the error - - if !symlink_path.is_symlink() { - if let Some(parent_dir) = symlink_path.parent() { - fs::create_dir_all(parent_dir).map_err(|error| { - ImportPackageError::CreateParentDir { - symlink_path: symlink_path.to_path_buf(), - error, - } - })?; - } - symlink_dir(save_path, symlink_path).map_err(|error| { - ImportPackageError::SymlinkDir { - symlink_path: symlink_path.to_path_buf(), - error, - } - })?; - } + symlink_pkg(save_path, symlink_path).map_err(ImportPackageError::SymlinkPackage)?; } _ => panic!("Not implemented yet"), } From 673c33660ed867e6236128ced857d468232ad5d8 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 9 Oct 2023 20:45:44 +0700 Subject: [PATCH 025/210] feat: propagate an error --- crates/package_manager/src/import_pkg.rs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/crates/package_manager/src/import_pkg.rs b/crates/package_manager/src/import_pkg.rs index d92ad3115..c12ddaa3c 100644 --- a/crates/package_manager/src/import_pkg.rs +++ b/crates/package_manager/src/import_pkg.rs @@ -1,23 +1,16 @@ -use crate::{create_cas_files, symlink_pkg, SymlinkPackageError}; +use crate::{create_cas_files, symlink_pkg, CreateCasFilesError, SymlinkPackageError}; use derive_more::{Display, Error}; use miette::Diagnostic; use pacquet_npmrc::PackageImportMethod; use std::{ collections::HashMap, ffi::OsString, - io, path::{Path, PathBuf}, }; #[derive(Debug, Display, Error, Diagnostic)] pub enum ImportPackageError { - #[display(fmt = "cannot create parent dir for {symlink_path:?}: {error}")] - CreateParentDir { - symlink_path: PathBuf, - #[error(source)] - error: io::Error, - }, - + CreateCasFiles(CreateCasFilesError), SymlinkPackage(SymlinkPackageError), } @@ -39,7 +32,8 @@ impl<'a> ImportPackage<'a> { tracing::info!(target: "pacquet::import", ?save_path, ?symlink_path, "Import package"); match method { PackageImportMethod::Auto => { - create_cas_files(save_path, cas_paths).expect("no write errors"); // TODO: properly propagate the error + create_cas_files(save_path, cas_paths) + .map_err(ImportPackageError::CreateCasFiles)?; symlink_pkg(save_path, symlink_path).map_err(ImportPackageError::SymlinkPackage)?; } _ => panic!("Not implemented yet"), From f61eaff1efefedd360ff86660ac70ac9e45df20b Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 9 Oct 2023 20:46:30 +0700 Subject: [PATCH 026/210] feat: panic on error --- crates/cli/src/commands/install.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/commands/install.rs index 4278ea22a..c5edeec1f 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/commands/install.rs @@ -153,7 +153,8 @@ impl PackageManager { .join("node_modules") .join(&name_str), &self.config.modules_dir.join(&name_str), - ); + ) + .expect("symlink pkg"); // TODO: properly propagate this error }); } From 8cfda547436e2a89498428581fe2c1eedbae5eca Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 9 Oct 2023 20:47:06 +0700 Subject: [PATCH 027/210] refactor: move symlink_pkg statement out of match the 2 things are now actually separate --- crates/package_manager/src/import_pkg.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/package_manager/src/import_pkg.rs b/crates/package_manager/src/import_pkg.rs index c12ddaa3c..3e18abc2b 100644 --- a/crates/package_manager/src/import_pkg.rs +++ b/crates/package_manager/src/import_pkg.rs @@ -34,11 +34,10 @@ impl<'a> ImportPackage<'a> { PackageImportMethod::Auto => { create_cas_files(save_path, cas_paths) .map_err(ImportPackageError::CreateCasFiles)?; - symlink_pkg(save_path, symlink_path).map_err(ImportPackageError::SymlinkPackage)?; } _ => panic!("Not implemented yet"), } - Ok(()) + symlink_pkg(save_path, symlink_path).map_err(ImportPackageError::SymlinkPackage) } } From f7fd47eb64d8d5702c94754edc1d49844f852354 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 9 Oct 2023 20:49:21 +0700 Subject: [PATCH 028/210] docs: ImportPackageError --- crates/package_manager/src/import_pkg.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/package_manager/src/import_pkg.rs b/crates/package_manager/src/import_pkg.rs index 3e18abc2b..80fc316f0 100644 --- a/crates/package_manager/src/import_pkg.rs +++ b/crates/package_manager/src/import_pkg.rs @@ -8,6 +8,7 @@ use std::{ path::{Path, PathBuf}, }; +/// Error type for [`ImportPackage`]. #[derive(Debug, Display, Error, Diagnostic)] pub enum ImportPackageError { CreateCasFiles(CreateCasFilesError), From 0290a15d89bfc9d87fd691162b1bef627385521a Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 9 Oct 2023 20:49:40 +0700 Subject: [PATCH 029/210] docs: ImportPackage::import_pkg --- crates/package_manager/src/import_pkg.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/package_manager/src/import_pkg.rs b/crates/package_manager/src/import_pkg.rs index 80fc316f0..1f274bbd8 100644 --- a/crates/package_manager/src/import_pkg.rs +++ b/crates/package_manager/src/import_pkg.rs @@ -27,6 +27,7 @@ pub struct ImportPackage<'a> { } impl<'a> ImportPackage<'a> { + /// Execute the subroutine. pub fn import_pkg(self) -> Result<(), ImportPackageError> { let ImportPackage { method, cas_paths, save_path, symlink_path } = self; From fa20e05ad0c8e52bcd774724605b9bda94a34efe Mon Sep 17 00:00:00 2001 From: khai96_ Date: Tue, 10 Oct 2023 01:33:38 +0700 Subject: [PATCH 030/210] refactor: move import_method to create_cas_files --- crates/package_manager/src/cas.rs | 8 ++++++++ crates/package_manager/src/import_pkg.rs | 10 +++------- crates/package_manager/src/virtual_dir.rs | 9 ++------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/crates/package_manager/src/cas.rs b/crates/package_manager/src/cas.rs index 4b90bd39f..72fb2ba60 100644 --- a/crates/package_manager/src/cas.rs +++ b/crates/package_manager/src/cas.rs @@ -1,6 +1,7 @@ use crate::{link_file, LinkFileError}; use derive_more::{Display, Error}; use miette::Diagnostic; +use pacquet_npmrc::PackageImportMethod; use rayon::prelude::*; use std::{ collections::HashMap, @@ -19,9 +20,16 @@ pub enum CreateCasFilesError { /// /// If `dir_path` already exists, do nothing. pub fn create_cas_files( + import_method: PackageImportMethod, dir_path: &Path, cas_paths: &HashMap, ) -> Result<(), CreateCasFilesError> { + assert_eq!( + import_method, + PackageImportMethod::Auto, + "Only PackageImportMethod::Auto is currently supported, but {dir_path:?} requires {import_method:?}", + ); + if dir_path.exists() { return Ok(()); } diff --git a/crates/package_manager/src/import_pkg.rs b/crates/package_manager/src/import_pkg.rs index 1f274bbd8..aaef7a6c4 100644 --- a/crates/package_manager/src/import_pkg.rs +++ b/crates/package_manager/src/import_pkg.rs @@ -32,13 +32,9 @@ impl<'a> ImportPackage<'a> { let ImportPackage { method, cas_paths, save_path, symlink_path } = self; tracing::info!(target: "pacquet::import", ?save_path, ?symlink_path, "Import package"); - match method { - PackageImportMethod::Auto => { - create_cas_files(save_path, cas_paths) - .map_err(ImportPackageError::CreateCasFiles)?; - } - _ => panic!("Not implemented yet"), - } + + create_cas_files(method, save_path, cas_paths) + .map_err(ImportPackageError::CreateCasFiles)?; symlink_pkg(save_path, symlink_path).map_err(ImportPackageError::SymlinkPackage) } diff --git a/crates/package_manager/src/virtual_dir.rs b/crates/package_manager/src/virtual_dir.rs index 13bd2deef..1dfa14de1 100644 --- a/crates/package_manager/src/virtual_dir.rs +++ b/crates/package_manager/src/virtual_dir.rs @@ -48,12 +48,6 @@ impl<'a> CreateVirtualDirBySnapshot<'a> { package_snapshot, } = self; - assert_eq!( - import_method, - PackageImportMethod::Auto, - "Only auto import method is supported, but {dependency_path} requires {import_method:?}", - ); - // node_modules/.pacquet/pkg-name@x.y.z/node_modules let virtual_node_modules_dir = virtual_store_dir .join(dependency_path.package_specifier.to_virtual_store_name()) @@ -68,7 +62,8 @@ impl<'a> CreateVirtualDirBySnapshot<'a> { // 1. Install the files from `cas_paths` let save_path = virtual_node_modules_dir.join(dependency_path.package_specifier.name.to_string()); - create_cas_files(&save_path, cas_paths).map_err(CreateVirtualDirError::CreateCasFiles)?; + create_cas_files(import_method, &save_path, cas_paths) + .map_err(CreateVirtualDirError::CreateCasFiles)?; // 2. Create the symlink layout if let Some(dependencies) = &package_snapshot.dependencies { From b853ba6e080b5d5a9e07244f037715630fadf0f4 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Tue, 10 Oct 2023 01:35:08 +0700 Subject: [PATCH 031/210] refactor: consistent naming --- crates/cli/src/package.rs | 2 +- crates/package_manager/src/import_pkg.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/cli/src/package.rs b/crates/cli/src/package.rs index 8a95ba8bb..2353677e2 100644 --- a/crates/cli/src/package.rs +++ b/crates/cli/src/package.rs @@ -72,7 +72,7 @@ async fn internal_fetch( .join(&package_version.name); ImportPackage { - method: config.package_import_method, + import_method: config.package_import_method, cas_paths: &cas_paths, save_path: &save_path, symlink_path: &symlink_path.join(&package_version.name), diff --git a/crates/package_manager/src/import_pkg.rs b/crates/package_manager/src/import_pkg.rs index aaef7a6c4..b90b72f60 100644 --- a/crates/package_manager/src/import_pkg.rs +++ b/crates/package_manager/src/import_pkg.rs @@ -16,11 +16,11 @@ pub enum ImportPackageError { } /// This subroutine does 2 things: -/// 1. Populate files into [`save_path`](Self::save_path) according to [`cas_paths`](Self::cas_paths) and [`method`](Self::method). +/// 1. Populate files into [`save_path`](Self::save_path) according to [`cas_paths`](Self::cas_paths) and [`import_method`](Self::import_method). /// 2. Create at [`symlink_path`](Self::symlink_path) which points to [`save_path`](Self::save_path). #[must_use] pub struct ImportPackage<'a> { - pub method: PackageImportMethod, + pub import_method: PackageImportMethod, pub cas_paths: &'a HashMap, pub save_path: &'a Path, pub symlink_path: &'a Path, @@ -29,11 +29,11 @@ pub struct ImportPackage<'a> { impl<'a> ImportPackage<'a> { /// Execute the subroutine. pub fn import_pkg(self) -> Result<(), ImportPackageError> { - let ImportPackage { method, cas_paths, save_path, symlink_path } = self; + let ImportPackage { import_method, cas_paths, save_path, symlink_path } = self; tracing::info!(target: "pacquet::import", ?save_path, ?symlink_path, "Import package"); - create_cas_files(method, save_path, cas_paths) + create_cas_files(import_method, save_path, cas_paths) .map_err(ImportPackageError::CreateCasFiles)?; symlink_pkg(save_path, symlink_path).map_err(ImportPackageError::SymlinkPackage) From e985e3d513b98f25c60332cad1396efee3b92785 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Tue, 10 Oct 2023 13:48:56 +0700 Subject: [PATCH 032/210] fix(ci): micro-benchmark I forgot to change the CI when I remove `micro-benchmark` from `.cargo/config.toml`. And since it was expected for the CI to fail, I didn't bother to check the error message. --- .github/workflows/micro-benchmark.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/micro-benchmark.yml b/.github/workflows/micro-benchmark.yml index bd8dc2850..c754c0a98 100644 --- a/.github/workflows/micro-benchmark.yml +++ b/.github/workflows/micro-benchmark.yml @@ -39,7 +39,7 @@ jobs: run: sleep 15s - name: Run Bench on Main Branch - run: cargo micro-benchmark --save-baseline main + run: cargo run --bin=micro-benchmark --release --save-baseline main - name: Checkout PR Branch uses: actions/checkout@v4 @@ -55,7 +55,7 @@ jobs: run: sleep 15s - name: Run Bench on PR Branch - run: cargo micro-benchmark --save-baseline pr + run: cargo run --bin=micro-benchmark --release --save-baseline pr - name: Upload benchmark results uses: actions/upload-artifact@v3 From 9fd3abbeba5f31be02ebff760faa418e85d4a26e Mon Sep 17 00:00:00 2001 From: khai96_ Date: Tue, 10 Oct 2023 14:14:03 +0700 Subject: [PATCH 033/210] refactor: remove ImportPackage --- crates/cli/src/package.rs | 18 ++++++----- crates/cli/src/package_manager.rs | 8 +++-- crates/package_manager/src/import_pkg.rs | 41 ------------------------ crates/package_manager/src/lib.rs | 2 -- 4 files changed, 16 insertions(+), 53 deletions(-) delete mode 100644 crates/package_manager/src/import_pkg.rs diff --git a/crates/cli/src/package.rs b/crates/cli/src/package.rs index 2353677e2..8205b17b3 100644 --- a/crates/cli/src/package.rs +++ b/crates/cli/src/package.rs @@ -1,8 +1,9 @@ use crate::package_manager::PackageManagerError; +use pacquet_diagnostics::tracing; use pacquet_lockfile::{DependencyPath, LockfileResolution, PackageSnapshot, PkgNameVerPeer}; use pacquet_npmrc::Npmrc; use pacquet_package_manager::CreateVirtualDirBySnapshot; -use pacquet_package_manager::ImportPackage; +use pacquet_package_manager::{create_cas_files, symlink_pkg}; use pacquet_registry::{Package, PackageVersion}; use pacquet_tarball::{download_tarball_to_store, Cache}; use pipe_trait::Pipe; @@ -71,13 +72,14 @@ async fn internal_fetch( .join("node_modules") .join(&package_version.name); - ImportPackage { - import_method: config.package_import_method, - cas_paths: &cas_paths, - save_path: &save_path, - symlink_path: &symlink_path.join(&package_version.name), - } - .import_pkg()?; + let symlink_path = symlink_path.join(&package_version.name); + + tracing::info!(target: "pacquet::import", ?save_path, ?symlink_path, "Import package"); + + create_cas_files(config.package_import_method, &save_path, &cas_paths) + .map_err(PackageManagerError::CreateCasFiles)?; + + symlink_pkg(&save_path, &symlink_path).map_err(PackageManagerError::SymlinkPackage)?; Ok(()) } diff --git a/crates/cli/src/package_manager.rs b/crates/cli/src/package_manager.rs index 9b43ede57..b3c08cd0c 100644 --- a/crates/cli/src/package_manager.rs +++ b/crates/cli/src/package_manager.rs @@ -7,7 +7,7 @@ use pacquet_diagnostics::{ use pacquet_lockfile::Lockfile; use pacquet_npmrc::Npmrc; use pacquet_package_json::PackageJson; -use pacquet_package_manager::{CreateVirtualDirError, ImportPackageError}; +use pacquet_package_manager::{CreateCasFilesError, CreateVirtualDirError, SymlinkPackageError}; use pacquet_tarball::Cache; #[derive(Error, Debug, Diagnostic)] @@ -39,7 +39,11 @@ pub enum PackageManagerError { #[error(transparent)] #[diagnostic(transparent)] - ImportPackage(#[from] ImportPackageError), + CreateCasFiles(CreateCasFilesError), + + #[error(transparent)] + #[diagnostic(transparent)] + SymlinkPackage(SymlinkPackageError), } pub struct PackageManager { diff --git a/crates/package_manager/src/import_pkg.rs b/crates/package_manager/src/import_pkg.rs deleted file mode 100644 index b90b72f60..000000000 --- a/crates/package_manager/src/import_pkg.rs +++ /dev/null @@ -1,41 +0,0 @@ -use crate::{create_cas_files, symlink_pkg, CreateCasFilesError, SymlinkPackageError}; -use derive_more::{Display, Error}; -use miette::Diagnostic; -use pacquet_npmrc::PackageImportMethod; -use std::{ - collections::HashMap, - ffi::OsString, - path::{Path, PathBuf}, -}; - -/// Error type for [`ImportPackage`]. -#[derive(Debug, Display, Error, Diagnostic)] -pub enum ImportPackageError { - CreateCasFiles(CreateCasFilesError), - SymlinkPackage(SymlinkPackageError), -} - -/// This subroutine does 2 things: -/// 1. Populate files into [`save_path`](Self::save_path) according to [`cas_paths`](Self::cas_paths) and [`import_method`](Self::import_method). -/// 2. Create at [`symlink_path`](Self::symlink_path) which points to [`save_path`](Self::save_path). -#[must_use] -pub struct ImportPackage<'a> { - pub import_method: PackageImportMethod, - pub cas_paths: &'a HashMap, - pub save_path: &'a Path, - pub symlink_path: &'a Path, -} - -impl<'a> ImportPackage<'a> { - /// Execute the subroutine. - pub fn import_pkg(self) -> Result<(), ImportPackageError> { - let ImportPackage { import_method, cas_paths, save_path, symlink_path } = self; - - tracing::info!(target: "pacquet::import", ?save_path, ?symlink_path, "Import package"); - - create_cas_files(import_method, save_path, cas_paths) - .map_err(ImportPackageError::CreateCasFiles)?; - - symlink_pkg(save_path, symlink_path).map_err(ImportPackageError::SymlinkPackage) - } -} diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index 9621d1ec2..34473af0e 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -1,12 +1,10 @@ mod cas; -mod import_pkg; mod link_file; mod symlink_layout; mod symlink_pkg; mod virtual_dir; pub use cas::{create_cas_files, CreateCasFilesError}; -pub use import_pkg::{ImportPackage, ImportPackageError}; pub use link_file::{link_file, LinkFileError}; pub use symlink_layout::create_symlink_layout; pub use symlink_pkg::{symlink_pkg, SymlinkPackageError}; From d55c05636c6983a8f75313a1c96fa3d63dfd6b7b Mon Sep 17 00:00:00 2001 From: khai96_ Date: Tue, 10 Oct 2023 14:14:44 +0700 Subject: [PATCH 034/210] refactor: fix a name --- crates/cli/src/package_manager.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli/src/package_manager.rs b/crates/cli/src/package_manager.rs index b3c08cd0c..5077c4e40 100644 --- a/crates/cli/src/package_manager.rs +++ b/crates/cli/src/package_manager.rs @@ -35,7 +35,7 @@ pub enum PackageManagerError { #[error(transparent)] #[diagnostic(transparent)] - CreateVirtdir(#[from] CreateVirtualDirError), + CreateVirtualDir(#[from] CreateVirtualDirError), #[error(transparent)] #[diagnostic(transparent)] From 123137dae46c43495f122e25ada9658e0a37f056 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Tue, 10 Oct 2023 14:22:25 +0700 Subject: [PATCH 035/210] refactor: explicit error conversion in preparation for a more meaningful error variants --- crates/cli/src/commands/add.rs | 26 +++++++++++++++----------- crates/cli/src/package.rs | 17 ++++++++++++----- crates/cli/src/package_manager.rs | 21 +++++++++++++-------- 3 files changed, 40 insertions(+), 24 deletions(-) diff --git a/crates/cli/src/commands/add.rs b/crates/cli/src/commands/add.rs index f72387c4e..7797a22b9 100644 --- a/crates/cli/src/commands/add.rs +++ b/crates/cli/src/commands/add.rs @@ -120,21 +120,25 @@ impl PackageManager { } } - self.package_json.add_dependency( - &args.package, - &latest_version.serialize(args.save_exact), - args.dependency_group(), - )?; + self.package_json + .add_dependency( + &args.package, + &latest_version.serialize(args.save_exact), + args.dependency_group(), + ) + .map_err(PackageManagerError::PackageJson)?; // Using --save-peer will add one or more packages to peerDependencies and // install them as dev dependencies if args.dependency_group() == DependencyGroup::Peer { - self.package_json.add_dependency( - &args.package, - &latest_version.serialize(args.save_exact), - DependencyGroup::Dev, - )?; + self.package_json + .add_dependency( + &args.package, + &latest_version.serialize(args.save_exact), + DependencyGroup::Dev, + ) + .map_err(PackageManagerError::PackageJson)?; } - self.package_json.save()?; + self.package_json.save().map_err(PackageManagerError::PackageJson)?; Ok(()) } diff --git a/crates/cli/src/package.rs b/crates/cli/src/package.rs index 8205b17b3..27ce906ea 100644 --- a/crates/cli/src/package.rs +++ b/crates/cli/src/package.rs @@ -26,7 +26,9 @@ pub async fn install_package_from_registry( version_range: &str, symlink_path: &Path, ) -> Result { - let package = Package::fetch_from_registry(name, http_client, &config.registry).await?; + let package = Package::fetch_from_registry(name, http_client, &config.registry) + .await + .map_err(PackageManagerError::Registry)?; let package_version = package.pinned_version(version_range).unwrap(); internal_fetch(tarball_cache, http_client, package_version, config, symlink_path).await?; Ok(package_version.to_owned()) @@ -41,7 +43,9 @@ pub async fn fetch_package_version_directly( symlink_path: &Path, ) -> Result { let package_version = - PackageVersion::fetch_from_registry(name, version, http_client, &config.registry).await?; + PackageVersion::fetch_from_registry(name, version, http_client, &config.registry) + .await + .map_err(PackageManagerError::Registry)?; internal_fetch(tarball_cache, http_client, &package_version, config, symlink_path).await?; Ok(package_version.to_owned()) } @@ -64,7 +68,8 @@ async fn internal_fetch( package_version.dist.unpacked_size, package_version.as_tarball_url(), ) - .await?; + .await + .map_err(PackageManagerError::Tarball)?; let save_path = config .virtual_store_dir @@ -126,7 +131,8 @@ pub async fn install_single_package_to_virtual_store( None, &tarball_url, ) - .await?; + .await + .map_err(PackageManagerError::Tarball)?; CreateVirtualDirBySnapshot { dependency_path, @@ -135,7 +141,8 @@ pub async fn install_single_package_to_virtual_store( import_method: config.package_import_method, package_snapshot, } - .create_virtual_dir_by_snapshot()?; + .create_virtual_dir_by_snapshot() + .map_err(PackageManagerError::CreateVirtualDir)?; Ok(()) } diff --git a/crates/cli/src/package_manager.rs b/crates/cli/src/package_manager.rs index 5077c4e40..d6b8e6bca 100644 --- a/crates/cli/src/package_manager.rs +++ b/crates/cli/src/package_manager.rs @@ -9,33 +9,34 @@ use pacquet_npmrc::Npmrc; use pacquet_package_json::PackageJson; use pacquet_package_manager::{CreateCasFilesError, CreateVirtualDirError, SymlinkPackageError}; use pacquet_tarball::Cache; +use pipe_trait::Pipe; #[derive(Error, Debug, Diagnostic)] #[non_exhaustive] pub enum PackageManagerError { #[error(transparent)] #[diagnostic(transparent)] - Tarball(#[from] pacquet_tarball::TarballError), + Tarball(pacquet_tarball::TarballError), #[error(transparent)] #[diagnostic(transparent)] - PackageJson(#[from] pacquet_package_json::PackageJsonError), + PackageJson(pacquet_package_json::PackageJsonError), #[error(transparent)] #[diagnostic(transparent)] - LoadLockfileError(#[from] pacquet_lockfile::LoadLockfileError), + LoadLockfileError(pacquet_lockfile::LoadLockfileError), #[error(transparent)] #[diagnostic(transparent)] - Registry(#[from] pacquet_registry::RegistryError), + Registry(pacquet_registry::RegistryError), #[error(transparent)] #[diagnostic(code(pacquet_package_manager::io_error))] - Io(#[from] io::Error), + Io(io::Error), #[error(transparent)] #[diagnostic(transparent)] - CreateVirtualDir(#[from] CreateVirtualDirError), + CreateVirtualDir(CreateVirtualDirError), #[error(transparent)] #[diagnostic(transparent)] @@ -61,8 +62,12 @@ impl PackageManager { ) -> Result { Ok(PackageManager { config, - package_json: PackageJson::create_if_needed(package_json_path.into())?, - lockfile: call_load_lockfile(config.lockfile, Lockfile::load_from_current_dir)?, + package_json: package_json_path + .into() + .pipe(PackageJson::create_if_needed) + .map_err(PackageManagerError::PackageJson)?, + lockfile: call_load_lockfile(config.lockfile, Lockfile::load_from_current_dir) + .map_err(PackageManagerError::LoadLockfileError)?, http_client: reqwest::Client::new(), tarball_cache: Cache::new(), }) From 0cb6cef806e2be9f2e47c40614f5229907037450 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Tue, 10 Oct 2023 14:23:18 +0700 Subject: [PATCH 036/210] refactor: remove unused error variant --- crates/cli/src/package_manager.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/crates/cli/src/package_manager.rs b/crates/cli/src/package_manager.rs index d6b8e6bca..0a490689c 100644 --- a/crates/cli/src/package_manager.rs +++ b/crates/cli/src/package_manager.rs @@ -1,4 +1,4 @@ -use std::{io, path::PathBuf}; +use std::path::PathBuf; use pacquet_diagnostics::{ miette::{self, Diagnostic}, @@ -30,10 +30,6 @@ pub enum PackageManagerError { #[diagnostic(transparent)] Registry(pacquet_registry::RegistryError), - #[error(transparent)] - #[diagnostic(code(pacquet_package_manager::io_error))] - Io(io::Error), - #[error(transparent)] #[diagnostic(transparent)] CreateVirtualDir(CreateVirtualDirError), From 0f502f9ae3ade2e5378bb70077775c33564dce75 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Tue, 10 Oct 2023 17:15:27 +0700 Subject: [PATCH 037/210] fix(ci): micro-benchmark (again) --- .github/workflows/micro-benchmark.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/micro-benchmark.yml b/.github/workflows/micro-benchmark.yml index c754c0a98..cac3d1114 100644 --- a/.github/workflows/micro-benchmark.yml +++ b/.github/workflows/micro-benchmark.yml @@ -39,7 +39,7 @@ jobs: run: sleep 15s - name: Run Bench on Main Branch - run: cargo run --bin=micro-benchmark --release --save-baseline main + run: cargo run --bin=micro-benchmark --release -- --save-baseline main - name: Checkout PR Branch uses: actions/checkout@v4 @@ -55,7 +55,7 @@ jobs: run: sleep 15s - name: Run Bench on PR Branch - run: cargo run --bin=micro-benchmark --release --save-baseline pr + run: cargo run --bin=micro-benchmark --release -- --save-baseline pr - name: Upload benchmark results uses: actions/upload-artifact@v3 From 80c699986bd944ee4ab8534715f2e74fc1e866b8 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Tue, 10 Oct 2023 17:34:59 +0700 Subject: [PATCH 038/210] fix(benchmark): fixture path --- tasks/micro-benchmark/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/micro-benchmark/src/main.rs b/tasks/micro-benchmark/src/main.rs index 4032e9e43..5ad072f2e 100644 --- a/tasks/micro-benchmark/src/main.rs +++ b/tasks/micro-benchmark/src/main.rs @@ -51,7 +51,7 @@ pub fn main() -> Result<(), String> { let mut server = mockito::Server::new(); let CliArgs { save_baseline } = CliArgs::parse(); let root = get_project_root().unwrap(); - let fixtures_folder = root.join("tasks/benchmark/fixtures"); + let fixtures_folder = root.join("tasks/micro-benchmark/fixtures"); let mut criterion = Criterion::default().without_plots(); if let Some(baseline) = save_baseline { From adbba37dd5507a71cde24be42cff641efe6091c1 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Tue, 10 Oct 2023 20:14:26 +0700 Subject: [PATCH 039/210] refactor: move a function --- Cargo.lock | 3 + crates/cli/src/commands/install.rs | 4 +- crates/cli/src/package.rs | 63 +------------------- crates/cli/src/package_manager.rs | 6 +- crates/package_manager/Cargo.toml | 3 + crates/package_manager/src/lib.rs | 2 + crates/package_manager/src/single_pkg.rs | 73 ++++++++++++++++++++++++ 7 files changed, 85 insertions(+), 69 deletions(-) create mode 100644 crates/package_manager/src/single_pkg.rs diff --git a/Cargo.lock b/Cargo.lock index d5fc04b7d..b9d0a80e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1393,8 +1393,11 @@ dependencies = [ "pacquet_fs", "pacquet_lockfile", "pacquet_npmrc", + "pacquet_tarball", + "pipe-trait", "rayon", "reflink-copy", + "reqwest", "tracing", ] diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/commands/install.rs index c5edeec1f..043d613e8 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/commands/install.rs @@ -1,4 +1,4 @@ -use crate::package::{install_package_from_registry, install_single_package_to_virtual_store}; +use crate::package::install_package_from_registry; use crate::package_manager::{PackageManager, PackageManagerError}; use async_recursion::async_recursion; use clap::Parser; @@ -8,7 +8,7 @@ use pacquet_lockfile::{ DependencyPath, Lockfile, PackageSnapshot, PkgName, PkgNameVerPeer, RootProjectSnapshot, }; use pacquet_package_json::DependencyGroup; -use pacquet_package_manager::symlink_pkg; +use pacquet_package_manager::{install_single_package_to_virtual_store, symlink_pkg}; use pacquet_registry::PackageVersion; use pipe_trait::Pipe; use rayon::prelude::*; diff --git a/crates/cli/src/package.rs b/crates/cli/src/package.rs index 27ce906ea..c2dda52fb 100644 --- a/crates/cli/src/package.rs +++ b/crates/cli/src/package.rs @@ -1,14 +1,11 @@ use crate::package_manager::PackageManagerError; use pacquet_diagnostics::tracing; -use pacquet_lockfile::{DependencyPath, LockfileResolution, PackageSnapshot, PkgNameVerPeer}; use pacquet_npmrc::Npmrc; -use pacquet_package_manager::CreateVirtualDirBySnapshot; use pacquet_package_manager::{create_cas_files, symlink_pkg}; use pacquet_registry::{Package, PackageVersion}; use pacquet_tarball::{download_tarball_to_store, Cache}; -use pipe_trait::Pipe; use reqwest::Client; -use std::{borrow::Cow, path::Path}; +use std::path::Path; /// This function execute the following and returns the package /// - retrieves the package from the registry @@ -89,64 +86,6 @@ async fn internal_fetch( Ok(()) } -pub async fn install_single_package_to_virtual_store( - tarball_cache: &Cache, - http_client: &Client, - config: &'static Npmrc, - dependency_path: &DependencyPath, - package_snapshot: &PackageSnapshot, -) -> Result<(), PackageManagerError> { - let PackageSnapshot { resolution, .. } = package_snapshot; - let DependencyPath { custom_registry, package_specifier } = dependency_path; - - let (tarball_url, integrity) = match resolution { - LockfileResolution::Tarball(tarball_resolution) => { - let integrity = tarball_resolution.integrity.as_deref().unwrap_or_else(|| { - // TODO: how to handle the absent of integrity field? - panic!("Current implementation requires integrity, but {dependency_path} doesn't have it"); - }); - (tarball_resolution.tarball.as_str().pipe(Cow::Borrowed), integrity) - } - LockfileResolution::Registry(registry_resolution) => { - let registry = custom_registry.as_ref().unwrap_or(&config.registry); - let registry = registry.strip_suffix('/').unwrap_or(registry); - let PkgNameVerPeer { name, suffix: ver_peer } = package_specifier; - let version = ver_peer.version(); - let bare_name = name.bare.as_str(); - let tarball_url = format!("{registry}/{name}/-/{bare_name}-{version}.tgz"); - let integrity = registry_resolution.integrity.as_str(); - (Cow::Owned(tarball_url), integrity) - } - LockfileResolution::Directory(_) | LockfileResolution::Git(_) => { - panic!("Only TarballResolution and RegistryResolution is supported at the moment, but {dependency_path} requires {resolution:?}"); - } - }; - - // TODO: skip when already exists in store? - let cas_paths = download_tarball_to_store( - tarball_cache, - http_client, - &config.store_dir, - integrity, - None, - &tarball_url, - ) - .await - .map_err(PackageManagerError::Tarball)?; - - CreateVirtualDirBySnapshot { - dependency_path, - virtual_store_dir: &config.virtual_store_dir, - cas_paths: &cas_paths, - import_method: config.package_import_method, - package_snapshot, - } - .create_virtual_dir_by_snapshot() - .map_err(PackageManagerError::CreateVirtualDir)?; - - Ok(()) -} - #[cfg(test)] mod tests { use crate::package::install_package_from_registry; diff --git a/crates/cli/src/package_manager.rs b/crates/cli/src/package_manager.rs index 0a490689c..eb5bdac2c 100644 --- a/crates/cli/src/package_manager.rs +++ b/crates/cli/src/package_manager.rs @@ -7,7 +7,7 @@ use pacquet_diagnostics::{ use pacquet_lockfile::Lockfile; use pacquet_npmrc::Npmrc; use pacquet_package_json::PackageJson; -use pacquet_package_manager::{CreateCasFilesError, CreateVirtualDirError, SymlinkPackageError}; +use pacquet_package_manager::{CreateCasFilesError, SymlinkPackageError}; use pacquet_tarball::Cache; use pipe_trait::Pipe; @@ -30,10 +30,6 @@ pub enum PackageManagerError { #[diagnostic(transparent)] Registry(pacquet_registry::RegistryError), - #[error(transparent)] - #[diagnostic(transparent)] - CreateVirtualDir(CreateVirtualDirError), - #[error(transparent)] #[diagnostic(transparent)] CreateCasFiles(CreateCasFilesError), diff --git a/crates/package_manager/Cargo.toml b/crates/package_manager/Cargo.toml index eea0a76f7..095485097 100644 --- a/crates/package_manager/Cargo.toml +++ b/crates/package_manager/Cargo.toml @@ -14,9 +14,12 @@ repository.workspace = true pacquet_fs = { workspace = true } pacquet_lockfile = { workspace = true } pacquet_npmrc = { workspace = true } +pacquet_tarball = { workspace = true } derive_more = { workspace = true } +pipe-trait = { workspace = true } rayon = { workspace = true } reflink-copy = { workspace = true } +reqwest = { workspace = true } tracing = { workspace = true } miette = { workspace = true } diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index 34473af0e..c8b459e87 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -1,11 +1,13 @@ mod cas; mod link_file; +mod single_pkg; mod symlink_layout; mod symlink_pkg; mod virtual_dir; pub use cas::{create_cas_files, CreateCasFilesError}; pub use link_file::{link_file, LinkFileError}; +pub use single_pkg::{install_single_package_to_virtual_store, SinglePackageError}; pub use symlink_layout::create_symlink_layout; pub use symlink_pkg::{symlink_pkg, SymlinkPackageError}; pub use virtual_dir::{CreateVirtualDirBySnapshot, CreateVirtualDirError}; diff --git a/crates/package_manager/src/single_pkg.rs b/crates/package_manager/src/single_pkg.rs new file mode 100644 index 000000000..a16c83ffe --- /dev/null +++ b/crates/package_manager/src/single_pkg.rs @@ -0,0 +1,73 @@ +use crate::{CreateVirtualDirBySnapshot, CreateVirtualDirError}; +use derive_more::{Display, Error}; +use miette::Diagnostic; +use pacquet_lockfile::{DependencyPath, LockfileResolution, PackageSnapshot, PkgNameVerPeer}; +use pacquet_npmrc::Npmrc; +use pacquet_tarball::{download_tarball_to_store, Cache, TarballError}; +use pipe_trait::Pipe; +use reqwest::Client; +use std::borrow::Cow; + +#[derive(Debug, Display, Error, Diagnostic)] +pub enum SinglePackageError { + DownloadTarball(TarballError), + CreateVirtualDir(CreateVirtualDirError), +} + +pub async fn install_single_package_to_virtual_store( + tarball_cache: &Cache, + http_client: &Client, + config: &'static Npmrc, + dependency_path: &DependencyPath, + package_snapshot: &PackageSnapshot, +) -> Result<(), SinglePackageError> { + let PackageSnapshot { resolution, .. } = package_snapshot; + let DependencyPath { custom_registry, package_specifier } = dependency_path; + + let (tarball_url, integrity) = match resolution { + LockfileResolution::Tarball(tarball_resolution) => { + let integrity = tarball_resolution.integrity.as_deref().unwrap_or_else(|| { + // TODO: how to handle the absent of integrity field? + panic!("Current implementation requires integrity, but {dependency_path} doesn't have it"); + }); + (tarball_resolution.tarball.as_str().pipe(Cow::Borrowed), integrity) + } + LockfileResolution::Registry(registry_resolution) => { + let registry = custom_registry.as_ref().unwrap_or(&config.registry); + let registry = registry.strip_suffix('/').unwrap_or(registry); + let PkgNameVerPeer { name, suffix: ver_peer } = package_specifier; + let version = ver_peer.version(); + let bare_name = name.bare.as_str(); + let tarball_url = format!("{registry}/{name}/-/{bare_name}-{version}.tgz"); + let integrity = registry_resolution.integrity.as_str(); + (Cow::Owned(tarball_url), integrity) + } + LockfileResolution::Directory(_) | LockfileResolution::Git(_) => { + panic!("Only TarballResolution and RegistryResolution is supported at the moment, but {dependency_path} requires {resolution:?}"); + } + }; + + // TODO: skip when already exists in store? + let cas_paths = download_tarball_to_store( + tarball_cache, + http_client, + &config.store_dir, + integrity, + None, + &tarball_url, + ) + .await + .map_err(SinglePackageError::DownloadTarball)?; + + CreateVirtualDirBySnapshot { + dependency_path, + virtual_store_dir: &config.virtual_store_dir, + cas_paths: &cas_paths, + import_method: config.package_import_method, + package_snapshot, + } + .create_virtual_dir_by_snapshot() + .map_err(SinglePackageError::CreateVirtualDir)?; + + Ok(()) +} From ddeb5776ab6be7c629f015d64293f01eec61e585 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Tue, 10 Oct 2023 20:15:34 +0700 Subject: [PATCH 040/210] docs: an unwrap --- crates/cli/src/commands/install.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/commands/install.rs index 043d613e8..f9aeedb3b 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/commands/install.rs @@ -112,7 +112,7 @@ impl PackageManager { package_snapshot, ) .await - .unwrap(); + .unwrap(); // TODO: properly propagate this error }) .pipe(future::join_all) .await; From a7494bc2bda40e5ddb0badb0bcec639d83a2c377 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Tue, 10 Oct 2023 20:21:24 +0700 Subject: [PATCH 041/210] refactor: InstallSinglePkgToVirtualDir --- crates/cli/src/commands/install.rs | 13 +-- crates/package_manager/src/lib.rs | 2 +- crates/package_manager/src/single_pkg.rs | 116 +++++++++++++---------- 3 files changed, 72 insertions(+), 59 deletions(-) diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/commands/install.rs index f9aeedb3b..564c61bb5 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/commands/install.rs @@ -8,7 +8,7 @@ use pacquet_lockfile::{ DependencyPath, Lockfile, PackageSnapshot, PkgName, PkgNameVerPeer, RootProjectSnapshot, }; use pacquet_package_json::DependencyGroup; -use pacquet_package_manager::{install_single_package_to_virtual_store, symlink_pkg}; +use pacquet_package_manager::{symlink_pkg, InstallSinglePkgToVirtualDir}; use pacquet_registry::PackageVersion; use pipe_trait::Pipe; use rayon::prelude::*; @@ -104,13 +104,14 @@ impl PackageManager { packages .iter() .map(|(dependency_path, package_snapshot)| async move { - install_single_package_to_virtual_store( - &self.tarball_cache, - &self.http_client, - self.config, + InstallSinglePkgToVirtualDir { + tarball_cache: &self.tarball_cache, + http_client: &self.http_client, + config: self.config, dependency_path, package_snapshot, - ) + } + .install() .await .unwrap(); // TODO: properly propagate this error }) diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index c8b459e87..c22b93d05 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -7,7 +7,7 @@ mod virtual_dir; pub use cas::{create_cas_files, CreateCasFilesError}; pub use link_file::{link_file, LinkFileError}; -pub use single_pkg::{install_single_package_to_virtual_store, SinglePackageError}; +pub use single_pkg::{InstallSinglePkgToVirtualDir, SinglePackageError}; pub use symlink_layout::create_symlink_layout; pub use symlink_pkg::{symlink_pkg, SymlinkPackageError}; pub use virtual_dir::{CreateVirtualDirBySnapshot, CreateVirtualDirError}; diff --git a/crates/package_manager/src/single_pkg.rs b/crates/package_manager/src/single_pkg.rs index a16c83ffe..b327df275 100644 --- a/crates/package_manager/src/single_pkg.rs +++ b/crates/package_manager/src/single_pkg.rs @@ -14,60 +14,72 @@ pub enum SinglePackageError { CreateVirtualDir(CreateVirtualDirError), } -pub async fn install_single_package_to_virtual_store( - tarball_cache: &Cache, - http_client: &Client, - config: &'static Npmrc, - dependency_path: &DependencyPath, - package_snapshot: &PackageSnapshot, -) -> Result<(), SinglePackageError> { - let PackageSnapshot { resolution, .. } = package_snapshot; - let DependencyPath { custom_registry, package_specifier } = dependency_path; +#[must_use] +pub struct InstallSinglePkgToVirtualDir<'a> { + pub tarball_cache: &'a Cache, + pub http_client: &'a Client, + pub config: &'static Npmrc, + pub dependency_path: &'a DependencyPath, + pub package_snapshot: &'a PackageSnapshot, +} - let (tarball_url, integrity) = match resolution { - LockfileResolution::Tarball(tarball_resolution) => { - let integrity = tarball_resolution.integrity.as_deref().unwrap_or_else(|| { - // TODO: how to handle the absent of integrity field? - panic!("Current implementation requires integrity, but {dependency_path} doesn't have it"); - }); - (tarball_resolution.tarball.as_str().pipe(Cow::Borrowed), integrity) - } - LockfileResolution::Registry(registry_resolution) => { - let registry = custom_registry.as_ref().unwrap_or(&config.registry); - let registry = registry.strip_suffix('/').unwrap_or(registry); - let PkgNameVerPeer { name, suffix: ver_peer } = package_specifier; - let version = ver_peer.version(); - let bare_name = name.bare.as_str(); - let tarball_url = format!("{registry}/{name}/-/{bare_name}-{version}.tgz"); - let integrity = registry_resolution.integrity.as_str(); - (Cow::Owned(tarball_url), integrity) - } - LockfileResolution::Directory(_) | LockfileResolution::Git(_) => { - panic!("Only TarballResolution and RegistryResolution is supported at the moment, but {dependency_path} requires {resolution:?}"); - } - }; +impl<'a> InstallSinglePkgToVirtualDir<'a> { + pub async fn install(self) -> Result<(), SinglePackageError> { + let InstallSinglePkgToVirtualDir { + tarball_cache, + http_client, + config, + dependency_path, + package_snapshot, + } = self; + let PackageSnapshot { resolution, .. } = package_snapshot; + let DependencyPath { custom_registry, package_specifier } = dependency_path; - // TODO: skip when already exists in store? - let cas_paths = download_tarball_to_store( - tarball_cache, - http_client, - &config.store_dir, - integrity, - None, - &tarball_url, - ) - .await - .map_err(SinglePackageError::DownloadTarball)?; + let (tarball_url, integrity) = match resolution { + LockfileResolution::Tarball(tarball_resolution) => { + let integrity = tarball_resolution.integrity.as_deref().unwrap_or_else(|| { + // TODO: how to handle the absent of integrity field? + panic!("Current implementation requires integrity, but {dependency_path} doesn't have it"); + }); + (tarball_resolution.tarball.as_str().pipe(Cow::Borrowed), integrity) + } + LockfileResolution::Registry(registry_resolution) => { + let registry = custom_registry.as_ref().unwrap_or(&config.registry); + let registry = registry.strip_suffix('/').unwrap_or(registry); + let PkgNameVerPeer { name, suffix: ver_peer } = package_specifier; + let version = ver_peer.version(); + let bare_name = name.bare.as_str(); + let tarball_url = format!("{registry}/{name}/-/{bare_name}-{version}.tgz"); + let integrity = registry_resolution.integrity.as_str(); + (Cow::Owned(tarball_url), integrity) + } + LockfileResolution::Directory(_) | LockfileResolution::Git(_) => { + panic!("Only TarballResolution and RegistryResolution is supported at the moment, but {dependency_path} requires {resolution:?}"); + } + }; - CreateVirtualDirBySnapshot { - dependency_path, - virtual_store_dir: &config.virtual_store_dir, - cas_paths: &cas_paths, - import_method: config.package_import_method, - package_snapshot, - } - .create_virtual_dir_by_snapshot() - .map_err(SinglePackageError::CreateVirtualDir)?; + // TODO: skip when already exists in store? + let cas_paths = download_tarball_to_store( + tarball_cache, + http_client, + &config.store_dir, + integrity, + None, + &tarball_url, + ) + .await + .map_err(SinglePackageError::DownloadTarball)?; + + CreateVirtualDirBySnapshot { + dependency_path, + virtual_store_dir: &config.virtual_store_dir, + cas_paths: &cas_paths, + import_method: config.package_import_method, + package_snapshot, + } + .create_virtual_dir_by_snapshot() + .map_err(SinglePackageError::CreateVirtualDir)?; - Ok(()) + Ok(()) + } } From aeaa4791a1b18f26994a1764c892fd6cf2250208 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Tue, 10 Oct 2023 20:31:23 +0700 Subject: [PATCH 042/210] docs: InstallSinglePkgToVirtualDir --- crates/package_manager/src/single_pkg.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/package_manager/src/single_pkg.rs b/crates/package_manager/src/single_pkg.rs index b327df275..7706c5b75 100644 --- a/crates/package_manager/src/single_pkg.rs +++ b/crates/package_manager/src/single_pkg.rs @@ -14,6 +14,8 @@ pub enum SinglePackageError { CreateVirtualDir(CreateVirtualDirError), } +/// This subroutine downloads a package tarball, extracts it, installs it to a virtual dir, +/// then creates the symlink layout for the package. #[must_use] pub struct InstallSinglePkgToVirtualDir<'a> { pub tarball_cache: &'a Cache, @@ -24,6 +26,7 @@ pub struct InstallSinglePkgToVirtualDir<'a> { } impl<'a> InstallSinglePkgToVirtualDir<'a> { + /// Execute the subroutine. pub async fn install(self) -> Result<(), SinglePackageError> { let InstallSinglePkgToVirtualDir { tarball_cache, From 36a300ba0092075e81dc3c07e04f4c9cf83af3c9 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Tue, 10 Oct 2023 20:32:14 +0700 Subject: [PATCH 043/210] docs: summary should be in one paragraph. --- crates/package_manager/src/virtual_dir.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/package_manager/src/virtual_dir.rs b/crates/package_manager/src/virtual_dir.rs index 1dfa14de1..ea841b66c 100644 --- a/crates/package_manager/src/virtual_dir.rs +++ b/crates/package_manager/src/virtual_dir.rs @@ -25,9 +25,7 @@ pub enum CreateVirtualDirError { CreateCasFiles(#[error(source)] CreateCasFilesError), } -/// This subroutine does 2 things: -/// 1. Install the files from `cas_paths` -/// 2. Create the symlink layout +/// This subroutine installs the files from `cas_paths` then creates the symlink layout. #[must_use] pub struct CreateVirtualDirBySnapshot<'a> { pub dependency_path: &'a DependencyPath, From 7e7a6af650c04f126d9c17959825528ee297e520 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Wed, 11 Oct 2023 02:22:20 +0700 Subject: [PATCH 044/210] docs: unwrap --- crates/cli/src/package.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli/src/package.rs b/crates/cli/src/package.rs index c2dda52fb..e97263a91 100644 --- a/crates/cli/src/package.rs +++ b/crates/cli/src/package.rs @@ -26,7 +26,7 @@ pub async fn install_package_from_registry( let package = Package::fetch_from_registry(name, http_client, &config.registry) .await .map_err(PackageManagerError::Registry)?; - let package_version = package.pinned_version(version_range).unwrap(); + let package_version = package.pinned_version(version_range).unwrap(); // TODO: propagate error for when no version satisfies range internal_fetch(tarball_cache, http_client, package_version, config, symlink_path).await?; Ok(package_version.to_owned()) } From f009373544d56a0606315bc0ad0cc947386bc6dc Mon Sep 17 00:00:00 2001 From: khai96_ Date: Wed, 11 Oct 2023 02:25:32 +0700 Subject: [PATCH 045/210] docs: plan --- crates/cli/src/package.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/cli/src/package.rs b/crates/cli/src/package.rs index e97263a91..e24b1dcee 100644 --- a/crates/cli/src/package.rs +++ b/crates/cli/src/package.rs @@ -23,6 +23,7 @@ pub async fn install_package_from_registry( version_range: &str, symlink_path: &Path, ) -> Result { + // TODO: if version_range is actually a version, fetch that version directly let package = Package::fetch_from_registry(name, http_client, &config.registry) .await .map_err(PackageManagerError::Registry)?; @@ -31,6 +32,7 @@ pub async fn install_package_from_registry( Ok(package_version.to_owned()) } +// TODO: this function should be removed once `pacquet add` support version ranges pub async fn fetch_package_version_directly( tarball_cache: &Cache, config: &'static Npmrc, From 87973dbcb7564dfe14f5109344ed69b0589ae76e Mon Sep 17 00:00:00 2001 From: khai96_ Date: Wed, 11 Oct 2023 12:11:54 +0700 Subject: [PATCH 046/210] docs: note the necessity --- crates/cli/src/package.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/cli/src/package.rs b/crates/cli/src/package.rs index e24b1dcee..f9e291149 100644 --- a/crates/cli/src/package.rs +++ b/crates/cli/src/package.rs @@ -49,6 +49,7 @@ pub async fn fetch_package_version_directly( Ok(package_version.to_owned()) } +// TODO: this function should cease to be necessary once `fetch_package_version_directly` is deleted. async fn internal_fetch( tarball_cache: &Cache, http_client: &Client, From 3810d27683a090342d8a1ade08bfa3fdc724877d Mon Sep 17 00:00:00 2001 From: khai96_ Date: Wed, 11 Oct 2023 15:13:43 +0700 Subject: [PATCH 047/210] perf(install): skip requesting index when pinned --- crates/cli/src/package.rs | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/crates/cli/src/package.rs b/crates/cli/src/package.rs index f9e291149..b059dae67 100644 --- a/crates/cli/src/package.rs +++ b/crates/cli/src/package.rs @@ -1,4 +1,5 @@ use crate::package_manager::PackageManagerError; +use node_semver::Version; use pacquet_diagnostics::tracing; use pacquet_npmrc::Npmrc; use pacquet_package_manager::{create_cas_files, symlink_pkg}; @@ -23,13 +24,26 @@ pub async fn install_package_from_registry( version_range: &str, symlink_path: &Path, ) -> Result { - // TODO: if version_range is actually a version, fetch that version directly - let package = Package::fetch_from_registry(name, http_client, &config.registry) - .await - .map_err(PackageManagerError::Registry)?; - let package_version = package.pinned_version(version_range).unwrap(); // TODO: propagate error for when no version satisfies range - internal_fetch(tarball_cache, http_client, package_version, config, symlink_path).await?; - Ok(package_version.to_owned()) + Ok(match Version::parse(version_range) { + Ok(version) => { + let package_version = + PackageVersion::fetch_from_registry(name, version, http_client, &config.registry) + .await + .map_err(PackageManagerError::Registry)?; + internal_fetch(tarball_cache, http_client, &package_version, config, symlink_path) + .await?; + package_version + } + Err(_) => { + let package = Package::fetch_from_registry(name, http_client, &config.registry) + .await + .map_err(PackageManagerError::Registry)?; + let package_version = package.pinned_version(version_range).unwrap(); // TODO: propagate error for when no version satisfies range + internal_fetch(tarball_cache, http_client, package_version, config, symlink_path) + .await?; + package_version.clone() + } + }) } // TODO: this function should be removed once `pacquet add` support version ranges From 00d49deba8ba4575007e8d5ed7d916ee862a5371 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Wed, 11 Oct 2023 15:15:51 +0700 Subject: [PATCH 048/210] refactor: change match to if let --- crates/cli/src/package.rs | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/crates/cli/src/package.rs b/crates/cli/src/package.rs index b059dae67..898864ba4 100644 --- a/crates/cli/src/package.rs +++ b/crates/cli/src/package.rs @@ -24,25 +24,20 @@ pub async fn install_package_from_registry( version_range: &str, symlink_path: &Path, ) -> Result { - Ok(match Version::parse(version_range) { - Ok(version) => { - let package_version = - PackageVersion::fetch_from_registry(name, version, http_client, &config.registry) - .await - .map_err(PackageManagerError::Registry)?; - internal_fetch(tarball_cache, http_client, &package_version, config, symlink_path) - .await?; - package_version - } - Err(_) => { - let package = Package::fetch_from_registry(name, http_client, &config.registry) + Ok(if let Ok(version) = Version::parse(version_range) { + let package_version = + PackageVersion::fetch_from_registry(name, version, http_client, &config.registry) .await .map_err(PackageManagerError::Registry)?; - let package_version = package.pinned_version(version_range).unwrap(); // TODO: propagate error for when no version satisfies range - internal_fetch(tarball_cache, http_client, package_version, config, symlink_path) - .await?; - package_version.clone() - } + internal_fetch(tarball_cache, http_client, &package_version, config, symlink_path).await?; + package_version + } else { + let package = Package::fetch_from_registry(name, http_client, &config.registry) + .await + .map_err(PackageManagerError::Registry)?; + let package_version = package.pinned_version(version_range).unwrap(); // TODO: propagate error for when no version satisfies range + internal_fetch(tarball_cache, http_client, package_version, config, symlink_path).await?; + package_version.clone() }) } From 038abe932411f76c4eeeb697e4420bc6cc4a2db9 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Wed, 11 Oct 2023 15:22:25 +0700 Subject: [PATCH 049/210] refactor: remove fetch_package_version_directly --- crates/cli/src/commands/add.rs | 6 +++--- crates/cli/src/package.rs | 17 ----------------- 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/crates/cli/src/commands/add.rs b/crates/cli/src/commands/add.rs index 7797a22b9..842226050 100644 --- a/crates/cli/src/commands/add.rs +++ b/crates/cli/src/commands/add.rs @@ -2,7 +2,7 @@ use clap::Parser; use std::collections::VecDeque; use crate::{ - package::{fetch_package_version_directly, install_package_from_registry}, + package::install_package_from_registry, package_manager::{PackageManager, PackageManagerError}, }; use futures_util::future; @@ -59,12 +59,12 @@ impl PackageManager { /// 5. Symlink all dependencies to node_modules/.pacquet/pkg@version/node_modules /// 6. Update package.json pub async fn add(&mut self, args: &AddCommandArgs) -> Result<(), PackageManagerError> { - let latest_version = fetch_package_version_directly( + let latest_version = install_package_from_registry( &self.tarball_cache, self.config, &self.http_client, &args.package, - "latest", + "*", &self.config.modules_dir, ) .await?; diff --git a/crates/cli/src/package.rs b/crates/cli/src/package.rs index 898864ba4..aafacad2e 100644 --- a/crates/cli/src/package.rs +++ b/crates/cli/src/package.rs @@ -41,23 +41,6 @@ pub async fn install_package_from_registry( }) } -// TODO: this function should be removed once `pacquet add` support version ranges -pub async fn fetch_package_version_directly( - tarball_cache: &Cache, - config: &'static Npmrc, - http_client: &Client, - name: &str, - version: &str, - symlink_path: &Path, -) -> Result { - let package_version = - PackageVersion::fetch_from_registry(name, version, http_client, &config.registry) - .await - .map_err(PackageManagerError::Registry)?; - internal_fetch(tarball_cache, http_client, &package_version, config, symlink_path).await?; - Ok(package_version.to_owned()) -} - // TODO: this function should cease to be necessary once `fetch_package_version_directly` is deleted. async fn internal_fetch( tarball_cache: &Cache, From a97254dea030f0581bde4772fdb0e72fed995a2e Mon Sep 17 00:00:00 2001 From: khai96_ Date: Wed, 11 Oct 2023 15:23:32 +0700 Subject: [PATCH 050/210] docs: remove a TODO --- crates/cli/src/package.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/cli/src/package.rs b/crates/cli/src/package.rs index aafacad2e..616edbb51 100644 --- a/crates/cli/src/package.rs +++ b/crates/cli/src/package.rs @@ -41,7 +41,6 @@ pub async fn install_package_from_registry( }) } -// TODO: this function should cease to be necessary once `fetch_package_version_directly` is deleted. async fn internal_fetch( tarball_cache: &Cache, http_client: &Client, From 6f95853d63a9a55923dd3a091f545637d75d2e03 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Wed, 11 Oct 2023 15:38:49 +0700 Subject: [PATCH 051/210] docs: planning --- crates/cli/src/package.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/cli/src/package.rs b/crates/cli/src/package.rs index 616edbb51..a18a5dd45 100644 --- a/crates/cli/src/package.rs +++ b/crates/cli/src/package.rs @@ -24,6 +24,7 @@ pub async fn install_package_from_registry( version_range: &str, symlink_path: &Path, ) -> Result { + // TODO: create a trait named FetchFromRegistry and implement it for Package, PackageVersion, and (would-be) LatestPackage Ok(if let Ok(version) = Version::parse(version_range) { let package_version = PackageVersion::fetch_from_registry(name, version, http_client, &config.registry) From 2b79f2002205750a2a89930c40dfb066fa1ecd27 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Wed, 11 Oct 2023 18:44:02 +0700 Subject: [PATCH 052/210] docs: change the plan --- crates/cli/src/package.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli/src/package.rs b/crates/cli/src/package.rs index a18a5dd45..22239cc31 100644 --- a/crates/cli/src/package.rs +++ b/crates/cli/src/package.rs @@ -24,7 +24,7 @@ pub async fn install_package_from_registry( version_range: &str, symlink_path: &Path, ) -> Result { - // TODO: create a trait named FetchFromRegistry and implement it for Package, PackageVersion, and (would-be) LatestPackage + // TODO: create a PackageTag enum with a parse function Ok(if let Ok(version) = Version::parse(version_range) { let package_version = PackageVersion::fetch_from_registry(name, version, http_client, &config.registry) From 3d3131d8674b99a0fb05c298d744060516b3bc32 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Thu, 12 Oct 2023 14:44:39 +0700 Subject: [PATCH 053/210] feat: PackageTag --- Cargo.lock | 1 + crates/cli/src/commands/add.rs | 11 ++++++----- crates/cli/src/commands/install.rs | 5 +++-- crates/cli/src/package.rs | 14 ++++++++------ crates/registry/Cargo.toml | 1 + crates/registry/src/lib.rs | 2 ++ crates/registry/src/package_tag.rs | 24 ++++++++++++++++++++++++ 7 files changed, 45 insertions(+), 13 deletions(-) create mode 100644 crates/registry/src/package_tag.rs diff --git a/Cargo.lock b/Cargo.lock index b9d0a80e3..4b95ddfe8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1405,6 +1405,7 @@ dependencies = [ name = "pacquet_registry" version = "0.0.1" dependencies = [ + "derive_more", "node-semver", "pacquet_diagnostics", "pipe-trait", diff --git a/crates/cli/src/commands/add.rs b/crates/cli/src/commands/add.rs index 842226050..c120d5fc2 100644 --- a/crates/cli/src/commands/add.rs +++ b/crates/cli/src/commands/add.rs @@ -1,4 +1,5 @@ use clap::Parser; +use node_semver::Version; use std::collections::VecDeque; use crate::{ @@ -8,7 +9,7 @@ use crate::{ use futures_util::future; use pacquet_diagnostics::miette::WrapErr; use pacquet_package_json::DependencyGroup; -use pacquet_registry::PackageVersion; +use pacquet_registry::{PackageTag, PackageVersion}; #[derive(Parser, Debug)] pub struct AddCommandArgs { @@ -59,12 +60,12 @@ impl PackageManager { /// 5. Symlink all dependencies to node_modules/.pacquet/pkg@version/node_modules /// 6. Update package.json pub async fn add(&mut self, args: &AddCommandArgs) -> Result<(), PackageManagerError> { - let latest_version = install_package_from_registry( + let latest_version = install_package_from_registry::( &self.tarball_cache, self.config, &self.http_client, &args.package, - "*", + "latest", &self.config.modules_dir, ) .await?; @@ -81,7 +82,7 @@ impl PackageManager { let direct_dependency_handles = latest_version.dependencies(self.config.auto_install_peers).map(|(name, version)| { - install_package_from_registry( + install_package_from_registry::( &self.tarball_cache, config, http_client, @@ -105,7 +106,7 @@ impl PackageManager { let handles = dependency.dependencies(self.config.auto_install_peers).map( |(name, version)| { - install_package_from_registry( + install_package_from_registry::( &self.tarball_cache, config, http_client, diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/commands/install.rs index 564c61bb5..8f12491d7 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/commands/install.rs @@ -3,6 +3,7 @@ use crate::package_manager::{PackageManager, PackageManagerError}; use async_recursion::async_recursion; use clap::Parser; use futures_util::future; +use node_semver::Version; use pacquet_diagnostics::tracing; use pacquet_lockfile::{ DependencyPath, Lockfile, PackageSnapshot, PkgName, PkgNameVerPeer, RootProjectSnapshot, @@ -75,7 +76,7 @@ impl PackageManager { package .dependencies(self.config.auto_install_peers) .map(|(name, version_range)| async { - let dependency = install_package_from_registry( + let dependency = install_package_from_registry::( &self.tarball_cache, self.config, &self.http_client, @@ -169,7 +170,7 @@ impl PackageManager { self.package_json .dependencies(dependency_options.dependency_groups()) .map(|(name, version_range)| async move { - let dependency = install_package_from_registry( + let dependency = install_package_from_registry::( &self.tarball_cache, self.config, &self.http_client, diff --git a/crates/cli/src/package.rs b/crates/cli/src/package.rs index 22239cc31..19744a26a 100644 --- a/crates/cli/src/package.rs +++ b/crates/cli/src/package.rs @@ -1,12 +1,11 @@ use crate::package_manager::PackageManagerError; -use node_semver::Version; use pacquet_diagnostics::tracing; use pacquet_npmrc::Npmrc; use pacquet_package_manager::{create_cas_files, symlink_pkg}; use pacquet_registry::{Package, PackageVersion}; use pacquet_tarball::{download_tarball_to_store, Cache}; use reqwest::Client; -use std::path::Path; +use std::{fmt::Display, path::Path, str::FromStr}; /// This function execute the following and returns the package /// - retrieves the package from the registry @@ -16,16 +15,19 @@ use std::path::Path; /// symlink_path will be appended by the name of the package. Therefore, /// it should be resolved into the node_modules folder of a subdependency such as /// `node_modules/.pacquet/fastify@1.0.0/node_modules`. -pub async fn install_package_from_registry( +pub async fn install_package_from_registry( tarball_cache: &Cache, config: &'static Npmrc, http_client: &Client, name: &str, version_range: &str, symlink_path: &Path, -) -> Result { +) -> Result +where + Tag: FromStr + Display, +{ // TODO: create a PackageTag enum with a parse function - Ok(if let Ok(version) = Version::parse(version_range) { + Ok(if let Ok(version) = version_range.parse::() { let package_version = PackageVersion::fetch_from_registry(name, version, http_client, &config.registry) .await @@ -127,7 +129,7 @@ mod tests { .pipe(Box::leak); let http_client = reqwest::Client::new(); let symlink_path = tempdir().unwrap(); - let package = install_package_from_registry( + let package = install_package_from_registry::( &Default::default(), config, &http_client, diff --git a/crates/registry/Cargo.toml b/crates/registry/Cargo.toml index f7d977b84..3002657d3 100644 --- a/crates/registry/Cargo.toml +++ b/crates/registry/Cargo.toml @@ -13,6 +13,7 @@ repository.workspace = true [dependencies] pacquet_diagnostics = { workspace = true } +derive_more = { workspace = true } reqwest = { workspace = true } node-semver = { workspace = true } pipe-trait = { workspace = true } diff --git a/crates/registry/src/lib.rs b/crates/registry/src/lib.rs index 16bce87ab..e86ee5d8c 100644 --- a/crates/registry/src/lib.rs +++ b/crates/registry/src/lib.rs @@ -1,9 +1,11 @@ mod package; mod package_distribution; +mod package_tag; mod package_version; pub use package::Package; pub use package_distribution::PackageDistribution; +pub use package_tag::PackageTag; pub use package_version::PackageVersion; use pacquet_diagnostics::{ diff --git a/crates/registry/src/package_tag.rs b/crates/registry/src/package_tag.rs new file mode 100644 index 000000000..30a4e8276 --- /dev/null +++ b/crates/registry/src/package_tag.rs @@ -0,0 +1,24 @@ +use derive_more::{Display, From, TryInto}; +use node_semver::{SemverError, Version}; +use std::str::FromStr; + +/// Version or tag that is attachable to a registry URL. +#[derive(Debug, Display, From, TryInto)] +pub enum PackageTag { + /// Literally `latest``. + #[display(fmt = "latest")] + Latest, + /// Pinned version. + Version(Version), +} + +impl FromStr for PackageTag { + type Err = SemverError; + fn from_str(value: &str) -> Result { + if value == "latest" { + Ok(PackageTag::Latest) + } else { + value.parse::().map(PackageTag::Version) + } + } +} From 419c10f95fa9ba4afc5e7c06f365bb0d26f8ed4a Mon Sep 17 00:00:00 2001 From: khai96_ Date: Thu, 12 Oct 2023 14:45:26 +0700 Subject: [PATCH 054/210] docs: missing feature --- crates/cli/src/commands/add.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli/src/commands/add.rs b/crates/cli/src/commands/add.rs index c120d5fc2..a283f297f 100644 --- a/crates/cli/src/commands/add.rs +++ b/crates/cli/src/commands/add.rs @@ -65,7 +65,7 @@ impl PackageManager { self.config, &self.http_client, &args.package, - "latest", + "latest", // TODO: add support for specifying tags &self.config.modules_dir, ) .await?; From c65e51fc861c35b7dd3e2519a1c3b0ac4eee7f03 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Thu, 12 Oct 2023 14:49:14 +0700 Subject: [PATCH 055/210] refactor: rename some variables --- crates/cli/src/package.rs | 4 ++-- crates/registry/src/package_version.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/cli/src/package.rs b/crates/cli/src/package.rs index 19744a26a..cb8efc0f1 100644 --- a/crates/cli/src/package.rs +++ b/crates/cli/src/package.rs @@ -27,9 +27,9 @@ where Tag: FromStr + Display, { // TODO: create a PackageTag enum with a parse function - Ok(if let Ok(version) = version_range.parse::() { + Ok(if let Ok(tag) = version_range.parse::() { let package_version = - PackageVersion::fetch_from_registry(name, version, http_client, &config.registry) + PackageVersion::fetch_from_registry(name, tag, http_client, &config.registry) .await .map_err(PackageManagerError::Registry)?; internal_fetch(tarball_cache, http_client, &package_version, config, symlink_path).await?; diff --git a/crates/registry/src/package_version.rs b/crates/registry/src/package_version.rs index 1580da92e..88009f732 100644 --- a/crates/registry/src/package_version.rs +++ b/crates/registry/src/package_version.rs @@ -25,11 +25,11 @@ impl PartialEq for PackageVersion { impl PackageVersion { pub async fn fetch_from_registry( name: &str, - version: impl Display, // TODO: change to node_semver::Version to increase resistance against programmer errors + tag: impl Display, // TODO: change to PackageTag to increase resistance against programmer errors http_client: &reqwest::Client, registry: &str, ) -> Result { - let url = || format!("{registry}{name}/{version}"); + let url = || format!("{registry}{name}/{tag}"); let network_error = |error| NetworkError { error, url: url() }; http_client From 35371b71949b77f3b867e13da970764c4cf51cd0 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Thu, 12 Oct 2023 14:51:31 +0700 Subject: [PATCH 056/210] refactor: guard against error --- crates/cli/src/package.rs | 8 ++++---- crates/registry/src/package_version.rs | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/cli/src/package.rs b/crates/cli/src/package.rs index cb8efc0f1..f528792a6 100644 --- a/crates/cli/src/package.rs +++ b/crates/cli/src/package.rs @@ -2,10 +2,10 @@ use crate::package_manager::PackageManagerError; use pacquet_diagnostics::tracing; use pacquet_npmrc::Npmrc; use pacquet_package_manager::{create_cas_files, symlink_pkg}; -use pacquet_registry::{Package, PackageVersion}; +use pacquet_registry::{Package, PackageTag, PackageVersion}; use pacquet_tarball::{download_tarball_to_store, Cache}; use reqwest::Client; -use std::{fmt::Display, path::Path, str::FromStr}; +use std::{path::Path, str::FromStr}; /// This function execute the following and returns the package /// - retrieves the package from the registry @@ -24,12 +24,12 @@ pub async fn install_package_from_registry( symlink_path: &Path, ) -> Result where - Tag: FromStr + Display, + Tag: FromStr + Into, { // TODO: create a PackageTag enum with a parse function Ok(if let Ok(tag) = version_range.parse::() { let package_version = - PackageVersion::fetch_from_registry(name, tag, http_client, &config.registry) + PackageVersion::fetch_from_registry(name, tag.into(), http_client, &config.registry) .await .map_err(PackageManagerError::Registry)?; internal_fetch(tarball_cache, http_client, &package_version, config, symlink_path).await?; diff --git a/crates/registry/src/package_version.rs b/crates/registry/src/package_version.rs index 88009f732..dcaca9217 100644 --- a/crates/registry/src/package_version.rs +++ b/crates/registry/src/package_version.rs @@ -1,9 +1,9 @@ -use std::{collections::HashMap, fmt::Display}; +use std::collections::HashMap; use pipe_trait::Pipe; use serde::{Deserialize, Serialize}; -use crate::{package_distribution::PackageDistribution, NetworkError, RegistryError}; +use crate::{package_distribution::PackageDistribution, NetworkError, PackageTag, RegistryError}; #[derive(Serialize, Deserialize, Debug, Clone, Eq)] #[serde(rename_all = "camelCase")] @@ -25,7 +25,7 @@ impl PartialEq for PackageVersion { impl PackageVersion { pub async fn fetch_from_registry( name: &str, - tag: impl Display, // TODO: change to PackageTag to increase resistance against programmer errors + tag: PackageTag, http_client: &reqwest::Client, registry: &str, ) -> Result { From 240b9a1fb063b84b8b7863f0ce8ebffe3d1687fc Mon Sep 17 00:00:00 2001 From: khai96_ Date: Thu, 12 Oct 2023 14:54:46 +0700 Subject: [PATCH 057/210] docs: remove outdated TODO --- crates/cli/src/package.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/cli/src/package.rs b/crates/cli/src/package.rs index f528792a6..3fb872901 100644 --- a/crates/cli/src/package.rs +++ b/crates/cli/src/package.rs @@ -26,7 +26,6 @@ pub async fn install_package_from_registry( where Tag: FromStr + Into, { - // TODO: create a PackageTag enum with a parse function Ok(if let Ok(tag) = version_range.parse::() { let package_version = PackageVersion::fetch_from_registry(name, tag.into(), http_client, &config.registry) From 2d04a8de88cf3c719dcd2e2693b1e1def46f2646 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Thu, 12 Oct 2023 17:02:09 +0700 Subject: [PATCH 058/210] refactor: rename --- crates/cli/src/commands/install.rs | 4 ++-- .../{single_pkg.rs => install_pkg_by_snapshot.rs} | 14 +++++++------- crates/package_manager/src/lib.rs | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) rename crates/package_manager/src/{single_pkg.rs => install_pkg_by_snapshot.rs} (89%) diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/commands/install.rs index 8f12491d7..f937fcb73 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/commands/install.rs @@ -9,7 +9,7 @@ use pacquet_lockfile::{ DependencyPath, Lockfile, PackageSnapshot, PkgName, PkgNameVerPeer, RootProjectSnapshot, }; use pacquet_package_json::DependencyGroup; -use pacquet_package_manager::{symlink_pkg, InstallSinglePkgToVirtualDir}; +use pacquet_package_manager::{symlink_pkg, InstallPackageBySnapshot}; use pacquet_registry::PackageVersion; use pipe_trait::Pipe; use rayon::prelude::*; @@ -105,7 +105,7 @@ impl PackageManager { packages .iter() .map(|(dependency_path, package_snapshot)| async move { - InstallSinglePkgToVirtualDir { + InstallPackageBySnapshot { tarball_cache: &self.tarball_cache, http_client: &self.http_client, config: self.config, diff --git a/crates/package_manager/src/single_pkg.rs b/crates/package_manager/src/install_pkg_by_snapshot.rs similarity index 89% rename from crates/package_manager/src/single_pkg.rs rename to crates/package_manager/src/install_pkg_by_snapshot.rs index 7706c5b75..718dcf0aa 100644 --- a/crates/package_manager/src/single_pkg.rs +++ b/crates/package_manager/src/install_pkg_by_snapshot.rs @@ -9,7 +9,7 @@ use reqwest::Client; use std::borrow::Cow; #[derive(Debug, Display, Error, Diagnostic)] -pub enum SinglePackageError { +pub enum InstallPackageBySnapshotError { DownloadTarball(TarballError), CreateVirtualDir(CreateVirtualDirError), } @@ -17,7 +17,7 @@ pub enum SinglePackageError { /// This subroutine downloads a package tarball, extracts it, installs it to a virtual dir, /// then creates the symlink layout for the package. #[must_use] -pub struct InstallSinglePkgToVirtualDir<'a> { +pub struct InstallPackageBySnapshot<'a> { pub tarball_cache: &'a Cache, pub http_client: &'a Client, pub config: &'static Npmrc, @@ -25,10 +25,10 @@ pub struct InstallSinglePkgToVirtualDir<'a> { pub package_snapshot: &'a PackageSnapshot, } -impl<'a> InstallSinglePkgToVirtualDir<'a> { +impl<'a> InstallPackageBySnapshot<'a> { /// Execute the subroutine. - pub async fn install(self) -> Result<(), SinglePackageError> { - let InstallSinglePkgToVirtualDir { + pub async fn install(self) -> Result<(), InstallPackageBySnapshotError> { + let InstallPackageBySnapshot { tarball_cache, http_client, config, @@ -71,7 +71,7 @@ impl<'a> InstallSinglePkgToVirtualDir<'a> { &tarball_url, ) .await - .map_err(SinglePackageError::DownloadTarball)?; + .map_err(InstallPackageBySnapshotError::DownloadTarball)?; CreateVirtualDirBySnapshot { dependency_path, @@ -81,7 +81,7 @@ impl<'a> InstallSinglePkgToVirtualDir<'a> { package_snapshot, } .create_virtual_dir_by_snapshot() - .map_err(SinglePackageError::CreateVirtualDir)?; + .map_err(InstallPackageBySnapshotError::CreateVirtualDir)?; Ok(()) } diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index c22b93d05..178cd24cb 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -1,13 +1,13 @@ mod cas; +mod install_pkg_by_snapshot; mod link_file; -mod single_pkg; mod symlink_layout; mod symlink_pkg; mod virtual_dir; pub use cas::{create_cas_files, CreateCasFilesError}; +pub use install_pkg_by_snapshot::{InstallPackageBySnapshot, InstallPackageBySnapshotError}; pub use link_file::{link_file, LinkFileError}; -pub use single_pkg::{InstallSinglePkgToVirtualDir, SinglePackageError}; pub use symlink_layout::create_symlink_layout; pub use symlink_pkg::{symlink_pkg, SymlinkPackageError}; pub use virtual_dir::{CreateVirtualDirBySnapshot, CreateVirtualDirError}; From 6c814256d8f9983765bed4bcec1722c61c866b20 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Thu, 12 Oct 2023 17:04:36 +0700 Subject: [PATCH 059/210] refactor: stop using `pkg` --- crates/cli/src/commands/install.rs | 4 ++-- crates/cli/src/package.rs | 4 ++-- ..._pkg_by_snapshot.rs => install_package_by_snapshot.rs} | 0 crates/package_manager/src/lib.rs | 8 ++++---- crates/package_manager/src/symlink_layout.rs | 4 ++-- .../src/{symlink_pkg.rs => symlink_package.rs} | 7 +++++-- 6 files changed, 15 insertions(+), 12 deletions(-) rename crates/package_manager/src/{install_pkg_by_snapshot.rs => install_package_by_snapshot.rs} (100%) rename crates/package_manager/src/{symlink_pkg.rs => symlink_package.rs} (91%) diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/commands/install.rs index f937fcb73..c5f8dcc25 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/commands/install.rs @@ -9,7 +9,7 @@ use pacquet_lockfile::{ DependencyPath, Lockfile, PackageSnapshot, PkgName, PkgNameVerPeer, RootProjectSnapshot, }; use pacquet_package_json::DependencyGroup; -use pacquet_package_manager::{symlink_pkg, InstallPackageBySnapshot}; +use pacquet_package_manager::{symlink_package, InstallPackageBySnapshot}; use pacquet_registry::PackageVersion; use pipe_trait::Pipe; use rayon::prelude::*; @@ -147,7 +147,7 @@ impl PackageManager { .to_virtual_store_name(); let name_str = name.to_string(); - symlink_pkg( + symlink_package( &self .config .virtual_store_dir diff --git a/crates/cli/src/package.rs b/crates/cli/src/package.rs index 3fb872901..cff24ce8b 100644 --- a/crates/cli/src/package.rs +++ b/crates/cli/src/package.rs @@ -1,7 +1,7 @@ use crate::package_manager::PackageManagerError; use pacquet_diagnostics::tracing; use pacquet_npmrc::Npmrc; -use pacquet_package_manager::{create_cas_files, symlink_pkg}; +use pacquet_package_manager::{create_cas_files, symlink_package}; use pacquet_registry::{Package, PackageTag, PackageVersion}; use pacquet_tarball::{download_tarball_to_store, Cache}; use reqwest::Client; @@ -77,7 +77,7 @@ async fn internal_fetch( create_cas_files(config.package_import_method, &save_path, &cas_paths) .map_err(PackageManagerError::CreateCasFiles)?; - symlink_pkg(&save_path, &symlink_path).map_err(PackageManagerError::SymlinkPackage)?; + symlink_package(&save_path, &symlink_path).map_err(PackageManagerError::SymlinkPackage)?; Ok(()) } diff --git a/crates/package_manager/src/install_pkg_by_snapshot.rs b/crates/package_manager/src/install_package_by_snapshot.rs similarity index 100% rename from crates/package_manager/src/install_pkg_by_snapshot.rs rename to crates/package_manager/src/install_package_by_snapshot.rs diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index 178cd24cb..4a9cec8cf 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -1,13 +1,13 @@ mod cas; -mod install_pkg_by_snapshot; +mod install_package_by_snapshot; mod link_file; mod symlink_layout; -mod symlink_pkg; +mod symlink_package; mod virtual_dir; pub use cas::{create_cas_files, CreateCasFilesError}; -pub use install_pkg_by_snapshot::{InstallPackageBySnapshot, InstallPackageBySnapshotError}; +pub use install_package_by_snapshot::{InstallPackageBySnapshot, InstallPackageBySnapshotError}; pub use link_file::{link_file, LinkFileError}; pub use symlink_layout::create_symlink_layout; -pub use symlink_pkg::{symlink_pkg, SymlinkPackageError}; +pub use symlink_package::{symlink_package, SymlinkPackageError}; pub use virtual_dir::{CreateVirtualDirBySnapshot, CreateVirtualDirError}; diff --git a/crates/package_manager/src/symlink_layout.rs b/crates/package_manager/src/symlink_layout.rs index d9fe56906..3abefacd2 100644 --- a/crates/package_manager/src/symlink_layout.rs +++ b/crates/package_manager/src/symlink_layout.rs @@ -1,4 +1,4 @@ -use crate::symlink_pkg; +use crate::symlink_package; use pacquet_lockfile::{PackageSnapshotDependency, PkgName, PkgNameVerPeer}; use rayon::prelude::*; use std::{collections::HashMap, path::Path}; @@ -22,7 +22,7 @@ pub fn create_symlink_layout( } }; let name_str = name.to_string(); - symlink_pkg( + symlink_package( &virtual_root.join(virtual_store_name).join("node_modules").join(&name_str), &virtual_node_modules_dir.join(&name_str), ) diff --git a/crates/package_manager/src/symlink_pkg.rs b/crates/package_manager/src/symlink_package.rs similarity index 91% rename from crates/package_manager/src/symlink_pkg.rs rename to crates/package_manager/src/symlink_package.rs index 5dc7f23ce..979ecc291 100644 --- a/crates/package_manager/src/symlink_pkg.rs +++ b/crates/package_manager/src/symlink_package.rs @@ -7,7 +7,7 @@ use std::{ path::{Path, PathBuf}, }; -/// Error type for [`symlink_pkg`]. +/// Error type for [`symlink_package`]. #[derive(Debug, Display, Error, Diagnostic)] pub enum SymlinkPackageError { #[display(fmt = "Failed to create directory at {dir:?}: {error}")] @@ -31,7 +31,10 @@ pub enum SymlinkPackageError { /// * If ancestors of `symlink_path` don't exist, they will be created recursively. /// * If `symlink_path` already exists, skip. /// * If `symlink_path` doesn't exist, a symlink pointing to `symlink_target` will be created. -pub fn symlink_pkg(symlink_target: &Path, symlink_path: &Path) -> Result<(), SymlinkPackageError> { +pub fn symlink_package( + symlink_target: &Path, + symlink_path: &Path, +) -> Result<(), SymlinkPackageError> { // NOTE: symlink target in pacquet is absolute yet in pnpm is relative // TODO: change symlink target to relative if let Some(parent) = symlink_path.parent() { From a1110d65067c4abf973d2ffe9638c41fcc91eca7 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Thu, 12 Oct 2023 17:05:26 +0700 Subject: [PATCH 060/210] docs: InstallPackageBySnapshotError --- crates/package_manager/src/install_package_by_snapshot.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/package_manager/src/install_package_by_snapshot.rs b/crates/package_manager/src/install_package_by_snapshot.rs index 718dcf0aa..e606aa40d 100644 --- a/crates/package_manager/src/install_package_by_snapshot.rs +++ b/crates/package_manager/src/install_package_by_snapshot.rs @@ -8,6 +8,7 @@ use pipe_trait::Pipe; use reqwest::Client; use std::borrow::Cow; +/// Error type of [`InstallPackageBySnapshot`]. #[derive(Debug, Display, Error, Diagnostic)] pub enum InstallPackageBySnapshotError { DownloadTarball(TarballError), From d4803fdbfef53464c9add549f84491ac98bff6e2 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Thu, 12 Oct 2023 17:21:18 +0700 Subject: [PATCH 061/210] refactor: move a function --- Cargo.lock | 5 +++ crates/cli/src/commands/add.rs | 13 +++---- crates/cli/src/commands/install.rs | 5 +-- crates/cli/src/lib.rs | 1 - crates/cli/src/package_manager.rs | 16 ++------- crates/package_manager/Cargo.toml | 15 +++++--- .../src/install_package_from_registry.rs} | 35 ++++++++++++------- crates/package_manager/src/lib.rs | 4 +++ 8 files changed, 54 insertions(+), 40 deletions(-) rename crates/{cli/src/package.rs => package_manager/src/install_package_from_registry.rs} (81%) diff --git a/Cargo.lock b/Cargo.lock index 4b95ddfe8..11c30fa11 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1390,14 +1390,19 @@ version = "0.0.1" dependencies = [ "derive_more", "miette", + "node-semver", "pacquet_fs", "pacquet_lockfile", "pacquet_npmrc", + "pacquet_registry", "pacquet_tarball", "pipe-trait", + "pretty_assertions", "rayon", "reflink-copy", "reqwest", + "tempfile", + "tokio", "tracing", ] diff --git a/crates/cli/src/commands/add.rs b/crates/cli/src/commands/add.rs index a283f297f..c97fbccb9 100644 --- a/crates/cli/src/commands/add.rs +++ b/crates/cli/src/commands/add.rs @@ -2,13 +2,11 @@ use clap::Parser; use node_semver::Version; use std::collections::VecDeque; -use crate::{ - package::install_package_from_registry, - package_manager::{PackageManager, PackageManagerError}, -}; -use futures_util::future; +use crate::package_manager::{PackageManager, PackageManagerError}; +use futures_util::{future, TryFutureExt}; use pacquet_diagnostics::miette::WrapErr; use pacquet_package_json::DependencyGroup; +use pacquet_package_manager::install_package_from_registry; use pacquet_registry::{PackageTag, PackageVersion}; #[derive(Parser, Debug)] @@ -68,7 +66,8 @@ impl PackageManager { "latest", // TODO: add support for specifying tags &self.config.modules_dir, ) - .await?; + .await + .map_err(PackageManagerError::InstallPackageFromRegistry)?; let package_node_modules_path = self .config .virtual_store_dir @@ -90,6 +89,7 @@ impl PackageManager { version, path, ) + .map_err(PackageManagerError::InstallPackageFromRegistry) }); queue.push_front(future::join_all(direct_dependency_handles).await); @@ -114,6 +114,7 @@ impl PackageManager { version, &node_modules_path, ) + .map_err(PackageManagerError::InstallPackageFromRegistry) }, ); diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/commands/install.rs index c5f8dcc25..60ab078f6 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/commands/install.rs @@ -1,4 +1,3 @@ -use crate::package::install_package_from_registry; use crate::package_manager::{PackageManager, PackageManagerError}; use async_recursion::async_recursion; use clap::Parser; @@ -9,7 +8,9 @@ use pacquet_lockfile::{ DependencyPath, Lockfile, PackageSnapshot, PkgName, PkgNameVerPeer, RootProjectSnapshot, }; use pacquet_package_json::DependencyGroup; -use pacquet_package_manager::{symlink_package, InstallPackageBySnapshot}; +use pacquet_package_manager::{ + install_package_from_registry, symlink_package, InstallPackageBySnapshot, +}; use pacquet_registry::PackageVersion; use pipe_trait::Pipe; use rayon::prelude::*; diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index 934449fe0..f58a2d9b4 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -1,6 +1,5 @@ mod commands; mod fs; -mod package; mod package_manager; use crate::package_manager::PackageManager; diff --git a/crates/cli/src/package_manager.rs b/crates/cli/src/package_manager.rs index eb5bdac2c..b27d2a3e2 100644 --- a/crates/cli/src/package_manager.rs +++ b/crates/cli/src/package_manager.rs @@ -7,17 +7,13 @@ use pacquet_diagnostics::{ use pacquet_lockfile::Lockfile; use pacquet_npmrc::Npmrc; use pacquet_package_json::PackageJson; -use pacquet_package_manager::{CreateCasFilesError, SymlinkPackageError}; +use pacquet_package_manager::InstallPackageFromRegistryError; use pacquet_tarball::Cache; use pipe_trait::Pipe; #[derive(Error, Debug, Diagnostic)] #[non_exhaustive] pub enum PackageManagerError { - #[error(transparent)] - #[diagnostic(transparent)] - Tarball(pacquet_tarball::TarballError), - #[error(transparent)] #[diagnostic(transparent)] PackageJson(pacquet_package_json::PackageJsonError), @@ -28,15 +24,7 @@ pub enum PackageManagerError { #[error(transparent)] #[diagnostic(transparent)] - Registry(pacquet_registry::RegistryError), - - #[error(transparent)] - #[diagnostic(transparent)] - CreateCasFiles(CreateCasFilesError), - - #[error(transparent)] - #[diagnostic(transparent)] - SymlinkPackage(SymlinkPackageError), + InstallPackageFromRegistry(InstallPackageFromRegistryError), } pub struct PackageManager { diff --git a/crates/package_manager/Cargo.toml b/crates/package_manager/Cargo.toml index 095485097..e53ac1a05 100644 --- a/crates/package_manager/Cargo.toml +++ b/crates/package_manager/Cargo.toml @@ -11,10 +11,11 @@ license.workspace = true repository.workspace = true [dependencies] -pacquet_fs = { workspace = true } -pacquet_lockfile = { workspace = true } -pacquet_npmrc = { workspace = true } -pacquet_tarball = { workspace = true } +pacquet_fs = { workspace = true } +pacquet_lockfile = { workspace = true } +pacquet_npmrc = { workspace = true } +pacquet_registry = { workspace = true } +pacquet_tarball = { workspace = true } derive_more = { workspace = true } pipe-trait = { workspace = true } @@ -23,3 +24,9 @@ reflink-copy = { workspace = true } reqwest = { workspace = true } tracing = { workspace = true } miette = { workspace = true } + +[dev-dependencies] +node-semver = { workspace = true } +pretty_assertions = { workspace = true } +tempfile = { workspace = true } +tokio = { workspace = true } diff --git a/crates/cli/src/package.rs b/crates/package_manager/src/install_package_from_registry.rs similarity index 81% rename from crates/cli/src/package.rs rename to crates/package_manager/src/install_package_from_registry.rs index cff24ce8b..4ca2b50f4 100644 --- a/crates/cli/src/package.rs +++ b/crates/package_manager/src/install_package_from_registry.rs @@ -1,12 +1,20 @@ -use crate::package_manager::PackageManagerError; -use pacquet_diagnostics::tracing; +use crate::{create_cas_files, symlink_package, CreateCasFilesError, SymlinkPackageError}; +use derive_more::{Display, Error}; +use miette::Diagnostic; use pacquet_npmrc::Npmrc; -use pacquet_package_manager::{create_cas_files, symlink_package}; -use pacquet_registry::{Package, PackageTag, PackageVersion}; -use pacquet_tarball::{download_tarball_to_store, Cache}; +use pacquet_registry::{Package, PackageTag, PackageVersion, RegistryError}; +use pacquet_tarball::{download_tarball_to_store, Cache, TarballError}; use reqwest::Client; use std::{path::Path, str::FromStr}; +#[derive(Debug, Display, Error, Diagnostic)] +pub enum InstallPackageFromRegistryError { + FetchFromRegistry(#[error(source)] RegistryError), + DownloadTarballToStore(#[error(source)] TarballError), + CreateCasFiles(#[error(source)] CreateCasFilesError), + SymlinkPackage(#[error(source)] SymlinkPackageError), +} + /// This function execute the following and returns the package /// - retrieves the package from the registry /// - extracts the tarball to global store directory (~/Library/../pacquet) @@ -22,7 +30,7 @@ pub async fn install_package_from_registry( name: &str, version_range: &str, symlink_path: &Path, -) -> Result +) -> Result where Tag: FromStr + Into, { @@ -30,13 +38,13 @@ where let package_version = PackageVersion::fetch_from_registry(name, tag.into(), http_client, &config.registry) .await - .map_err(PackageManagerError::Registry)?; + .map_err(InstallPackageFromRegistryError::FetchFromRegistry)?; internal_fetch(tarball_cache, http_client, &package_version, config, symlink_path).await?; package_version } else { let package = Package::fetch_from_registry(name, http_client, &config.registry) .await - .map_err(PackageManagerError::Registry)?; + .map_err(InstallPackageFromRegistryError::FetchFromRegistry)?; let package_version = package.pinned_version(version_range).unwrap(); // TODO: propagate error for when no version satisfies range internal_fetch(tarball_cache, http_client, package_version, config, symlink_path).await?; package_version.clone() @@ -49,7 +57,7 @@ async fn internal_fetch( package_version: &PackageVersion, config: &'static Npmrc, symlink_path: &Path, -) -> Result<(), PackageManagerError> { +) -> Result<(), InstallPackageFromRegistryError> { let store_folder_name = package_version.to_virtual_store_name(); // TODO: skip when it already exists in store? @@ -62,7 +70,7 @@ async fn internal_fetch( package_version.as_tarball_url(), ) .await - .map_err(PackageManagerError::Tarball)?; + .map_err(InstallPackageFromRegistryError::DownloadTarballToStore)?; let save_path = config .virtual_store_dir @@ -75,16 +83,17 @@ async fn internal_fetch( tracing::info!(target: "pacquet::import", ?save_path, ?symlink_path, "Import package"); create_cas_files(config.package_import_method, &save_path, &cas_paths) - .map_err(PackageManagerError::CreateCasFiles)?; + .map_err(InstallPackageFromRegistryError::CreateCasFiles)?; - symlink_package(&save_path, &symlink_path).map_err(PackageManagerError::SymlinkPackage)?; + symlink_package(&save_path, &symlink_path) + .map_err(InstallPackageFromRegistryError::SymlinkPackage)?; Ok(()) } #[cfg(test)] mod tests { - use crate::package::install_package_from_registry; + use super::*; use node_semver::Version; use pacquet_npmrc::Npmrc; use pipe_trait::Pipe; diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index 4a9cec8cf..a6862ba37 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -1,5 +1,6 @@ mod cas; mod install_package_by_snapshot; +mod install_package_from_registry; mod link_file; mod symlink_layout; mod symlink_package; @@ -7,6 +8,9 @@ mod virtual_dir; pub use cas::{create_cas_files, CreateCasFilesError}; pub use install_package_by_snapshot::{InstallPackageBySnapshot, InstallPackageBySnapshotError}; +pub use install_package_from_registry::{ + install_package_from_registry, InstallPackageFromRegistryError, +}; pub use link_file::{link_file, LinkFileError}; pub use symlink_layout::create_symlink_layout; pub use symlink_package::{symlink_package, SymlinkPackageError}; From 2f4a2e1a8f40e46b3c03ceead7309c0a3c306f54 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Thu, 12 Oct 2023 19:39:05 +0700 Subject: [PATCH 062/210] refactor: InstallPackageFromRegistry --- crates/cli/src/commands/add.rs | 42 +++++---- crates/cli/src/commands/install.rs | 30 +++--- .../src/install_package_from_registry.rs | 94 ++++++++++++------- crates/package_manager/src/lib.rs | 2 +- 4 files changed, 97 insertions(+), 71 deletions(-) diff --git a/crates/cli/src/commands/add.rs b/crates/cli/src/commands/add.rs index c97fbccb9..7a09128ea 100644 --- a/crates/cli/src/commands/add.rs +++ b/crates/cli/src/commands/add.rs @@ -6,7 +6,7 @@ use crate::package_manager::{PackageManager, PackageManagerError}; use futures_util::{future, TryFutureExt}; use pacquet_diagnostics::miette::WrapErr; use pacquet_package_json::DependencyGroup; -use pacquet_package_manager::install_package_from_registry; +use pacquet_package_manager::InstallPackageFromRegistry; use pacquet_registry::{PackageTag, PackageVersion}; #[derive(Parser, Debug)] @@ -58,14 +58,15 @@ impl PackageManager { /// 5. Symlink all dependencies to node_modules/.pacquet/pkg@version/node_modules /// 6. Update package.json pub async fn add(&mut self, args: &AddCommandArgs) -> Result<(), PackageManagerError> { - let latest_version = install_package_from_registry::( - &self.tarball_cache, - self.config, - &self.http_client, - &args.package, - "latest", // TODO: add support for specifying tags - &self.config.modules_dir, - ) + let latest_version = InstallPackageFromRegistry { + tarball_cache: &self.tarball_cache, + config: self.config, + http_client: &self.http_client, + name: &args.package, + version_range: "latest", // TODO: add support for specifying tags + symlink_path: &self.config.modules_dir, + } + .install::() .await .map_err(PackageManagerError::InstallPackageFromRegistry)?; let package_node_modules_path = self @@ -77,18 +78,18 @@ impl PackageManager { let mut queue: VecDeque>> = VecDeque::new(); let config = &self.config; let http_client = &self.http_client; - let path = &package_node_modules_path; let direct_dependency_handles = latest_version.dependencies(self.config.auto_install_peers).map(|(name, version)| { - install_package_from_registry::( - &self.tarball_cache, + InstallPackageFromRegistry { + tarball_cache: &self.tarball_cache, config, http_client, name, - version, - path, - ) + version_range: version, + symlink_path: &package_node_modules_path, + } + .install::() .map_err(PackageManagerError::InstallPackageFromRegistry) }); @@ -106,14 +107,15 @@ impl PackageManager { let handles = dependency.dependencies(self.config.auto_install_peers).map( |(name, version)| { - install_package_from_registry::( - &self.tarball_cache, + InstallPackageFromRegistry { + tarball_cache: &self.tarball_cache, config, http_client, name, - version, - &node_modules_path, - ) + version_range: version, + symlink_path: &node_modules_path, + } + .install::() .map_err(PackageManagerError::InstallPackageFromRegistry) }, ); diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/commands/install.rs index 60ab078f6..b8d2a132e 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/commands/install.rs @@ -9,7 +9,7 @@ use pacquet_lockfile::{ }; use pacquet_package_json::DependencyGroup; use pacquet_package_manager::{ - install_package_from_registry, symlink_package, InstallPackageBySnapshot, + symlink_package, InstallPackageBySnapshot, InstallPackageFromRegistry, }; use pacquet_registry::PackageVersion; use pipe_trait::Pipe; @@ -77,16 +77,17 @@ impl PackageManager { package .dependencies(self.config.auto_install_peers) .map(|(name, version_range)| async { - let dependency = install_package_from_registry::( - &self.tarball_cache, - self.config, - &self.http_client, + let dependency = InstallPackageFromRegistry { + tarball_cache: &self.tarball_cache, + config: self.config, + http_client: &self.http_client, name, version_range, - &node_modules_path, - ) + symlink_path: &node_modules_path, + } + .install::() .await - .unwrap(); + .unwrap(); // TODO: proper error propagation self.install_dependencies_from_registry(&dependency).await; }) .pipe(future::join_all) @@ -171,14 +172,15 @@ impl PackageManager { self.package_json .dependencies(dependency_options.dependency_groups()) .map(|(name, version_range)| async move { - let dependency = install_package_from_registry::( - &self.tarball_cache, - self.config, - &self.http_client, + let dependency = InstallPackageFromRegistry { + tarball_cache: &self.tarball_cache, + config: self.config, + http_client: &self.http_client, name, version_range, - &self.config.modules_dir, - ) + symlink_path: &self.config.modules_dir, + } + .install::() .await .unwrap(); self.install_dependencies_from_registry(&dependency).await; diff --git a/crates/package_manager/src/install_package_from_registry.rs b/crates/package_manager/src/install_package_from_registry.rs index 4ca2b50f4..80bc1c710 100644 --- a/crates/package_manager/src/install_package_from_registry.rs +++ b/crates/package_manager/src/install_package_from_registry.rs @@ -15,40 +15,61 @@ pub enum InstallPackageFromRegistryError { SymlinkPackage(#[error(source)] SymlinkPackageError), } -/// This function execute the following and returns the package -/// - retrieves the package from the registry -/// - extracts the tarball to global store directory (~/Library/../pacquet) -/// - links global store directory to virtual dir (node_modules/.pacquet/..) +/// This subroutine executes the following and returns the package +/// * Retrieves the package from the registry +/// * Extracts the tarball to global store directory (~/Library/../pacquet) +/// * Links global store directory to virtual dir (node_modules/.pacquet/..) /// -/// symlink_path will be appended by the name of the package. Therefore, +/// `symlink_path` will be appended by the name of the package. Therefore, /// it should be resolved into the node_modules folder of a subdependency such as /// `node_modules/.pacquet/fastify@1.0.0/node_modules`. -pub async fn install_package_from_registry( - tarball_cache: &Cache, - config: &'static Npmrc, - http_client: &Client, - name: &str, - version_range: &str, - symlink_path: &Path, -) -> Result -where - Tag: FromStr + Into, -{ - Ok(if let Ok(tag) = version_range.parse::() { - let package_version = - PackageVersion::fetch_from_registry(name, tag.into(), http_client, &config.registry) - .await - .map_err(InstallPackageFromRegistryError::FetchFromRegistry)?; - internal_fetch(tarball_cache, http_client, &package_version, config, symlink_path).await?; - package_version - } else { - let package = Package::fetch_from_registry(name, http_client, &config.registry) +#[must_use] +pub struct InstallPackageFromRegistry<'a> { + pub tarball_cache: &'a Cache, + pub config: &'static Npmrc, + pub http_client: &'a Client, + pub name: &'a str, + pub version_range: &'a str, + pub symlink_path: &'a Path, +} + +impl<'a> InstallPackageFromRegistry<'a> { + /// Execute the subroutine. + pub async fn install(self) -> Result + where + Tag: FromStr + Into, + { + let &InstallPackageFromRegistry { + tarball_cache, + config, + http_client, + name, + version_range, + symlink_path, + } = &self; + + Ok(if let Ok(tag) = version_range.parse::() { + let package_version = PackageVersion::fetch_from_registry( + name, + tag.into(), + http_client, + &config.registry, + ) .await .map_err(InstallPackageFromRegistryError::FetchFromRegistry)?; - let package_version = package.pinned_version(version_range).unwrap(); // TODO: propagate error for when no version satisfies range - internal_fetch(tarball_cache, http_client, package_version, config, symlink_path).await?; - package_version.clone() - }) + internal_fetch(tarball_cache, http_client, &package_version, config, symlink_path) + .await?; + package_version + } else { + let package = Package::fetch_from_registry(name, http_client, &config.registry) + .await + .map_err(InstallPackageFromRegistryError::FetchFromRegistry)?; + let package_version = package.pinned_version(version_range).unwrap(); // TODO: propagate error for when no version satisfies range + internal_fetch(tarball_cache, http_client, package_version, config, symlink_path) + .await?; + package_version.clone() + }) + } } async fn internal_fetch( @@ -137,14 +158,15 @@ mod tests { .pipe(Box::leak); let http_client = reqwest::Client::new(); let symlink_path = tempdir().unwrap(); - let package = install_package_from_registry::( - &Default::default(), + let package = InstallPackageFromRegistry { + tarball_cache: &Default::default(), config, - &http_client, - "fast-querystring", - "1.0.0", - symlink_path.path(), - ) + http_client: &http_client, + name: "fast-querystring", + version_range: "1.0.0", + symlink_path: symlink_path.path(), + } + .install::() .await .unwrap(); diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index a6862ba37..817ccf735 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -9,7 +9,7 @@ mod virtual_dir; pub use cas::{create_cas_files, CreateCasFilesError}; pub use install_package_by_snapshot::{InstallPackageBySnapshot, InstallPackageBySnapshotError}; pub use install_package_from_registry::{ - install_package_from_registry, InstallPackageFromRegistryError, + InstallPackageFromRegistry, InstallPackageFromRegistryError, }; pub use link_file::{link_file, LinkFileError}; pub use symlink_layout::create_symlink_layout; From d909f97f801fbf384410d5664e68d1747255524c Mon Sep 17 00:00:00 2001 From: khai96_ Date: Thu, 12 Oct 2023 19:43:51 +0700 Subject: [PATCH 063/210] refactor: turn `internal_fetch` into a method --- .../src/install_package_from_registry.rs | 93 +++++++++---------- 1 file changed, 42 insertions(+), 51 deletions(-) diff --git a/crates/package_manager/src/install_package_from_registry.rs b/crates/package_manager/src/install_package_from_registry.rs index 80bc1c710..c7770c66d 100644 --- a/crates/package_manager/src/install_package_from_registry.rs +++ b/crates/package_manager/src/install_package_from_registry.rs @@ -39,14 +39,7 @@ impl<'a> InstallPackageFromRegistry<'a> { where Tag: FromStr + Into, { - let &InstallPackageFromRegistry { - tarball_cache, - config, - http_client, - name, - version_range, - symlink_path, - } = &self; + let &InstallPackageFromRegistry { config, http_client, name, version_range, .. } = &self; Ok(if let Ok(tag) = version_range.parse::() { let package_version = PackageVersion::fetch_from_registry( @@ -57,59 +50,57 @@ impl<'a> InstallPackageFromRegistry<'a> { ) .await .map_err(InstallPackageFromRegistryError::FetchFromRegistry)?; - internal_fetch(tarball_cache, http_client, &package_version, config, symlink_path) - .await?; + self.internal_fetch(&package_version).await?; package_version } else { let package = Package::fetch_from_registry(name, http_client, &config.registry) .await .map_err(InstallPackageFromRegistryError::FetchFromRegistry)?; let package_version = package.pinned_version(version_range).unwrap(); // TODO: propagate error for when no version satisfies range - internal_fetch(tarball_cache, http_client, package_version, config, symlink_path) - .await?; + self.internal_fetch(package_version).await?; package_version.clone() }) } -} -async fn internal_fetch( - tarball_cache: &Cache, - http_client: &Client, - package_version: &PackageVersion, - config: &'static Npmrc, - symlink_path: &Path, -) -> Result<(), InstallPackageFromRegistryError> { - let store_folder_name = package_version.to_virtual_store_name(); - - // TODO: skip when it already exists in store? - let cas_paths = download_tarball_to_store( - tarball_cache, - http_client, - &config.store_dir, - package_version.dist.integrity.as_ref().expect("has integrity field"), - package_version.dist.unpacked_size, - package_version.as_tarball_url(), - ) - .await - .map_err(InstallPackageFromRegistryError::DownloadTarballToStore)?; - - let save_path = config - .virtual_store_dir - .join(store_folder_name) - .join("node_modules") - .join(&package_version.name); - - let symlink_path = symlink_path.join(&package_version.name); - - tracing::info!(target: "pacquet::import", ?save_path, ?symlink_path, "Import package"); - - create_cas_files(config.package_import_method, &save_path, &cas_paths) - .map_err(InstallPackageFromRegistryError::CreateCasFiles)?; - - symlink_package(&save_path, &symlink_path) - .map_err(InstallPackageFromRegistryError::SymlinkPackage)?; - - Ok(()) + async fn internal_fetch( + self, + package_version: &PackageVersion, + ) -> Result<(), InstallPackageFromRegistryError> { + let InstallPackageFromRegistry { tarball_cache, config, http_client, symlink_path, .. } = + self; + + let store_folder_name = package_version.to_virtual_store_name(); + + // TODO: skip when it already exists in store? + let cas_paths = download_tarball_to_store( + tarball_cache, + http_client, + &config.store_dir, + package_version.dist.integrity.as_ref().expect("has integrity field"), + package_version.dist.unpacked_size, + package_version.as_tarball_url(), + ) + .await + .map_err(InstallPackageFromRegistryError::DownloadTarballToStore)?; + + let save_path = config + .virtual_store_dir + .join(store_folder_name) + .join("node_modules") + .join(&package_version.name); + + let symlink_path = symlink_path.join(&package_version.name); + + tracing::info!(target: "pacquet::import", ?save_path, ?symlink_path, "Import package"); + + create_cas_files(config.package_import_method, &save_path, &cas_paths) + .map_err(InstallPackageFromRegistryError::CreateCasFiles)?; + + symlink_package(&save_path, &symlink_path) + .map_err(InstallPackageFromRegistryError::SymlinkPackage)?; + + Ok(()) + } } #[cfg(test)] From fcaa74eb171294e91319bf6112a89eeb4fbaaec1 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Thu, 12 Oct 2023 19:45:53 +0700 Subject: [PATCH 064/210] refactor: rename a method --- crates/package_manager/src/install_package_from_registry.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/package_manager/src/install_package_from_registry.rs b/crates/package_manager/src/install_package_from_registry.rs index c7770c66d..a1a1a5271 100644 --- a/crates/package_manager/src/install_package_from_registry.rs +++ b/crates/package_manager/src/install_package_from_registry.rs @@ -50,19 +50,19 @@ impl<'a> InstallPackageFromRegistry<'a> { ) .await .map_err(InstallPackageFromRegistryError::FetchFromRegistry)?; - self.internal_fetch(&package_version).await?; + self.install_package_version(&package_version).await?; package_version } else { let package = Package::fetch_from_registry(name, http_client, &config.registry) .await .map_err(InstallPackageFromRegistryError::FetchFromRegistry)?; let package_version = package.pinned_version(version_range).unwrap(); // TODO: propagate error for when no version satisfies range - self.internal_fetch(package_version).await?; + self.install_package_version(package_version).await?; package_version.clone() }) } - async fn internal_fetch( + async fn install_package_version( self, package_version: &PackageVersion, ) -> Result<(), InstallPackageFromRegistryError> { From b6b1a52ba0be3c420d13f940c8b5cb1f9ddf03ce Mon Sep 17 00:00:00 2001 From: khai96_ Date: Thu, 12 Oct 2023 19:52:38 +0700 Subject: [PATCH 065/210] refactor: correct a field name --- crates/cli/src/commands/add.rs | 6 +++--- crates/cli/src/commands/install.rs | 4 ++-- .../src/install_package_from_registry.rs | 15 ++++++++------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/crates/cli/src/commands/add.rs b/crates/cli/src/commands/add.rs index 7a09128ea..21f16a059 100644 --- a/crates/cli/src/commands/add.rs +++ b/crates/cli/src/commands/add.rs @@ -64,7 +64,7 @@ impl PackageManager { http_client: &self.http_client, name: &args.package, version_range: "latest", // TODO: add support for specifying tags - symlink_path: &self.config.modules_dir, + node_modules_dir: &self.config.modules_dir, } .install::() .await @@ -87,7 +87,7 @@ impl PackageManager { http_client, name, version_range: version, - symlink_path: &package_node_modules_path, + node_modules_dir: &package_node_modules_path, } .install::() .map_err(PackageManagerError::InstallPackageFromRegistry) @@ -113,7 +113,7 @@ impl PackageManager { http_client, name, version_range: version, - symlink_path: &node_modules_path, + node_modules_dir: &node_modules_path, } .install::() .map_err(PackageManagerError::InstallPackageFromRegistry) diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/commands/install.rs index b8d2a132e..6fa6a41a3 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/commands/install.rs @@ -83,7 +83,7 @@ impl PackageManager { http_client: &self.http_client, name, version_range, - symlink_path: &node_modules_path, + node_modules_dir: &node_modules_path, } .install::() .await @@ -178,7 +178,7 @@ impl PackageManager { http_client: &self.http_client, name, version_range, - symlink_path: &self.config.modules_dir, + node_modules_dir: &self.config.modules_dir, } .install::() .await diff --git a/crates/package_manager/src/install_package_from_registry.rs b/crates/package_manager/src/install_package_from_registry.rs index a1a1a5271..bb8742bd5 100644 --- a/crates/package_manager/src/install_package_from_registry.rs +++ b/crates/package_manager/src/install_package_from_registry.rs @@ -30,7 +30,7 @@ pub struct InstallPackageFromRegistry<'a> { pub http_client: &'a Client, pub name: &'a str, pub version_range: &'a str, - pub symlink_path: &'a Path, + pub node_modules_dir: &'a Path, } impl<'a> InstallPackageFromRegistry<'a> { @@ -66,8 +66,9 @@ impl<'a> InstallPackageFromRegistry<'a> { self, package_version: &PackageVersion, ) -> Result<(), InstallPackageFromRegistryError> { - let InstallPackageFromRegistry { tarball_cache, config, http_client, symlink_path, .. } = - self; + let InstallPackageFromRegistry { + tarball_cache, config, http_client, node_modules_dir, .. + } = self; let store_folder_name = package_version.to_virtual_store_name(); @@ -89,7 +90,7 @@ impl<'a> InstallPackageFromRegistry<'a> { .join("node_modules") .join(&package_version.name); - let symlink_path = symlink_path.join(&package_version.name); + let symlink_path = node_modules_dir.join(&package_version.name); tracing::info!(target: "pacquet::import", ?save_path, ?symlink_path, "Import package"); @@ -148,14 +149,14 @@ mod tests { .pipe(Box::new) .pipe(Box::leak); let http_client = reqwest::Client::new(); - let symlink_path = tempdir().unwrap(); + let node_modules_dir = tempdir().unwrap(); let package = InstallPackageFromRegistry { tarball_cache: &Default::default(), config, http_client: &http_client, name: "fast-querystring", version_range: "1.0.0", - symlink_path: symlink_path.path(), + node_modules_dir: node_modules_dir.path(), } .install::() .await @@ -176,7 +177,7 @@ mod tests { // Make sure the symlink is resolving to the correct path assert_eq!( - fs::read_link(symlink_path.path().join(&package.name)).unwrap(), + fs::read_link(node_modules_dir.path().join(&package.name)).unwrap(), virtual_store_path ); } From c26c9e7ffe2c5fbbd1ae0ac0513eaa006c893242 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Thu, 12 Oct 2023 19:53:26 +0700 Subject: [PATCH 066/210] docs: InstallPackageFromRegistryError --- crates/package_manager/src/install_package_from_registry.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/package_manager/src/install_package_from_registry.rs b/crates/package_manager/src/install_package_from_registry.rs index bb8742bd5..6dd078c00 100644 --- a/crates/package_manager/src/install_package_from_registry.rs +++ b/crates/package_manager/src/install_package_from_registry.rs @@ -7,6 +7,7 @@ use pacquet_tarball::{download_tarball_to_store, Cache, TarballError}; use reqwest::Client; use std::{path::Path, str::FromStr}; +/// Error type of [`InstallPackageFromRegistry`]. #[derive(Debug, Display, Error, Diagnostic)] pub enum InstallPackageFromRegistryError { FetchFromRegistry(#[error(source)] RegistryError), From 26c9f402f7d196e3b1bbc43a98912d8a28c8791e Mon Sep 17 00:00:00 2001 From: khai96_ Date: Thu, 12 Oct 2023 20:04:54 +0700 Subject: [PATCH 067/210] docs: fields --- crates/package_manager/src/install_package_by_snapshot.rs | 5 +++++ crates/package_manager/src/install_package_from_registry.rs | 6 ++++++ crates/package_manager/src/virtual_dir.rs | 5 +++++ 3 files changed, 16 insertions(+) diff --git a/crates/package_manager/src/install_package_by_snapshot.rs b/crates/package_manager/src/install_package_by_snapshot.rs index e606aa40d..b37bba33e 100644 --- a/crates/package_manager/src/install_package_by_snapshot.rs +++ b/crates/package_manager/src/install_package_by_snapshot.rs @@ -19,10 +19,15 @@ pub enum InstallPackageBySnapshotError { /// then creates the symlink layout for the package. #[must_use] pub struct InstallPackageBySnapshot<'a> { + /// Shared cache that store downloaded tarballs. pub tarball_cache: &'a Cache, + /// HTTP client to make HTTP requests. pub http_client: &'a Client, + /// Configuration read from `.npmrc`. pub config: &'static Npmrc, + /// Key of the package map from the lockfile. pub dependency_path: &'a DependencyPath, + /// Value of the package map from the lockfile. pub package_snapshot: &'a PackageSnapshot, } diff --git a/crates/package_manager/src/install_package_from_registry.rs b/crates/package_manager/src/install_package_from_registry.rs index 6dd078c00..493ec9aec 100644 --- a/crates/package_manager/src/install_package_from_registry.rs +++ b/crates/package_manager/src/install_package_from_registry.rs @@ -26,11 +26,17 @@ pub enum InstallPackageFromRegistryError { /// `node_modules/.pacquet/fastify@1.0.0/node_modules`. #[must_use] pub struct InstallPackageFromRegistry<'a> { + /// Shared cache that store downloaded tarballs. pub tarball_cache: &'a Cache, + /// Configuration read from `.npmrc`. pub config: &'static Npmrc, + /// HTTP client to make HTTP requests. pub http_client: &'a Client, + /// Name of the package to be installed. pub name: &'a str, + /// Version range of the package to be installed. pub version_range: &'a str, + /// Path to a `node_modules` directory. pub node_modules_dir: &'a Path, } diff --git a/crates/package_manager/src/virtual_dir.rs b/crates/package_manager/src/virtual_dir.rs index ea841b66c..5dbea5738 100644 --- a/crates/package_manager/src/virtual_dir.rs +++ b/crates/package_manager/src/virtual_dir.rs @@ -28,10 +28,15 @@ pub enum CreateVirtualDirError { /// This subroutine installs the files from `cas_paths` then creates the symlink layout. #[must_use] pub struct CreateVirtualDirBySnapshot<'a> { + /// Key of the package map from the lockfile. pub dependency_path: &'a DependencyPath, + /// Path to the virtual store dir (usually canonical paths of `node_modules/.pacquet`). pub virtual_store_dir: &'a Path, + /// CAS files map. pub cas_paths: &'a HashMap, + /// Import method. pub import_method: PackageImportMethod, + /// Value of the package map from the lockfile. pub package_snapshot: &'a PackageSnapshot, } From 21787a4b08404c9446b195425fc79745b6361186 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Thu, 12 Oct 2023 20:05:34 +0700 Subject: [PATCH 068/210] docs: linkify --- crates/package_manager/src/virtual_dir.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/package_manager/src/virtual_dir.rs b/crates/package_manager/src/virtual_dir.rs index 5dbea5738..2d14d6eb1 100644 --- a/crates/package_manager/src/virtual_dir.rs +++ b/crates/package_manager/src/virtual_dir.rs @@ -25,7 +25,7 @@ pub enum CreateVirtualDirError { CreateCasFiles(#[error(source)] CreateCasFilesError), } -/// This subroutine installs the files from `cas_paths` then creates the symlink layout. +/// This subroutine installs the files from [`cas_paths`](Self::cas_paths) then creates the symlink layout. #[must_use] pub struct CreateVirtualDirBySnapshot<'a> { /// Key of the package map from the lockfile. From 8ed71997c5ac32350365324157239b6f895e5c9f Mon Sep 17 00:00:00 2001 From: khai96_ Date: Thu, 12 Oct 2023 20:11:54 +0700 Subject: [PATCH 069/210] refactor: rearrange some fields --- crates/cli/src/commands/add.rs | 8 ++++---- crates/cli/src/commands/install.rs | 8 ++++---- .../src/install_package_by_snapshot.rs | 2 +- .../src/install_package_from_registry.rs | 12 ++++++------ crates/package_manager/src/virtual_dir.rs | 6 +++--- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/crates/cli/src/commands/add.rs b/crates/cli/src/commands/add.rs index 21f16a059..a45f58c77 100644 --- a/crates/cli/src/commands/add.rs +++ b/crates/cli/src/commands/add.rs @@ -83,11 +83,11 @@ impl PackageManager { latest_version.dependencies(self.config.auto_install_peers).map(|(name, version)| { InstallPackageFromRegistry { tarball_cache: &self.tarball_cache, - config, http_client, + config, + node_modules_dir: &package_node_modules_path, name, version_range: version, - node_modules_dir: &package_node_modules_path, } .install::() .map_err(PackageManagerError::InstallPackageFromRegistry) @@ -109,11 +109,11 @@ impl PackageManager { |(name, version)| { InstallPackageFromRegistry { tarball_cache: &self.tarball_cache, - config, http_client, + config, + node_modules_dir: &node_modules_path, name, version_range: version, - node_modules_dir: &node_modules_path, } .install::() .map_err(PackageManagerError::InstallPackageFromRegistry) diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/commands/install.rs index 6fa6a41a3..4068061e6 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/commands/install.rs @@ -79,11 +79,11 @@ impl PackageManager { .map(|(name, version_range)| async { let dependency = InstallPackageFromRegistry { tarball_cache: &self.tarball_cache, - config: self.config, http_client: &self.http_client, + config: self.config, + node_modules_dir: &node_modules_path, name, version_range, - node_modules_dir: &node_modules_path, } .install::() .await @@ -174,11 +174,11 @@ impl PackageManager { .map(|(name, version_range)| async move { let dependency = InstallPackageFromRegistry { tarball_cache: &self.tarball_cache, - config: self.config, http_client: &self.http_client, + config: self.config, + node_modules_dir: &self.config.modules_dir, name, version_range, - node_modules_dir: &self.config.modules_dir, } .install::() .await diff --git a/crates/package_manager/src/install_package_by_snapshot.rs b/crates/package_manager/src/install_package_by_snapshot.rs index b37bba33e..bc0b3b8b8 100644 --- a/crates/package_manager/src/install_package_by_snapshot.rs +++ b/crates/package_manager/src/install_package_by_snapshot.rs @@ -80,10 +80,10 @@ impl<'a> InstallPackageBySnapshot<'a> { .map_err(InstallPackageBySnapshotError::DownloadTarball)?; CreateVirtualDirBySnapshot { - dependency_path, virtual_store_dir: &config.virtual_store_dir, cas_paths: &cas_paths, import_method: config.package_import_method, + dependency_path, package_snapshot, } .create_virtual_dir_by_snapshot() diff --git a/crates/package_manager/src/install_package_from_registry.rs b/crates/package_manager/src/install_package_from_registry.rs index 493ec9aec..4edb11bf6 100644 --- a/crates/package_manager/src/install_package_from_registry.rs +++ b/crates/package_manager/src/install_package_from_registry.rs @@ -28,16 +28,16 @@ pub enum InstallPackageFromRegistryError { pub struct InstallPackageFromRegistry<'a> { /// Shared cache that store downloaded tarballs. pub tarball_cache: &'a Cache, - /// Configuration read from `.npmrc`. - pub config: &'static Npmrc, /// HTTP client to make HTTP requests. pub http_client: &'a Client, + /// Configuration read from `.npmrc`. + pub config: &'static Npmrc, + /// Path to a `node_modules` directory. + pub node_modules_dir: &'a Path, /// Name of the package to be installed. pub name: &'a str, /// Version range of the package to be installed. pub version_range: &'a str, - /// Path to a `node_modules` directory. - pub node_modules_dir: &'a Path, } impl<'a> InstallPackageFromRegistry<'a> { @@ -46,7 +46,7 @@ impl<'a> InstallPackageFromRegistry<'a> { where Tag: FromStr + Into, { - let &InstallPackageFromRegistry { config, http_client, name, version_range, .. } = &self; + let &InstallPackageFromRegistry { http_client, config, name, version_range, .. } = &self; Ok(if let Ok(tag) = version_range.parse::() { let package_version = PackageVersion::fetch_from_registry( @@ -74,7 +74,7 @@ impl<'a> InstallPackageFromRegistry<'a> { package_version: &PackageVersion, ) -> Result<(), InstallPackageFromRegistryError> { let InstallPackageFromRegistry { - tarball_cache, config, http_client, node_modules_dir, .. + tarball_cache, http_client, config, node_modules_dir, .. } = self; let store_folder_name = package_version.to_virtual_store_name(); diff --git a/crates/package_manager/src/virtual_dir.rs b/crates/package_manager/src/virtual_dir.rs index 2d14d6eb1..9677b3feb 100644 --- a/crates/package_manager/src/virtual_dir.rs +++ b/crates/package_manager/src/virtual_dir.rs @@ -28,14 +28,14 @@ pub enum CreateVirtualDirError { /// This subroutine installs the files from [`cas_paths`](Self::cas_paths) then creates the symlink layout. #[must_use] pub struct CreateVirtualDirBySnapshot<'a> { - /// Key of the package map from the lockfile. - pub dependency_path: &'a DependencyPath, /// Path to the virtual store dir (usually canonical paths of `node_modules/.pacquet`). pub virtual_store_dir: &'a Path, /// CAS files map. pub cas_paths: &'a HashMap, /// Import method. pub import_method: PackageImportMethod, + /// Key of the package map from the lockfile. + pub dependency_path: &'a DependencyPath, /// Value of the package map from the lockfile. pub package_snapshot: &'a PackageSnapshot, } @@ -44,10 +44,10 @@ impl<'a> CreateVirtualDirBySnapshot<'a> { /// Execute the subroutine. pub fn create_virtual_dir_by_snapshot(self) -> Result<(), CreateVirtualDirError> { let CreateVirtualDirBySnapshot { - dependency_path, virtual_store_dir, cas_paths, import_method, + dependency_path, package_snapshot, } = self; From 4d0f6d41ea8f26c4aec7a9f0784defb918e126d1 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Thu, 12 Oct 2023 23:11:49 +0700 Subject: [PATCH 070/210] refactor: move a function --- Cargo.lock | 1 + crates/cli/src/commands/install.rs | 46 +++++------------- crates/package_manager/Cargo.toml | 1 + crates/package_manager/src/lib.rs | 2 + crates/package_manager/src/virtual_store.rs | 53 +++++++++++++++++++++ 5 files changed, 69 insertions(+), 34 deletions(-) create mode 100644 crates/package_manager/src/virtual_store.rs diff --git a/Cargo.lock b/Cargo.lock index 11c30fa11..cdc739536 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1389,6 +1389,7 @@ name = "pacquet_package_manager" version = "0.0.1" dependencies = [ "derive_more", + "futures-util", "miette", "node-semver", "pacquet_fs", diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/commands/install.rs index 4068061e6..c23b2952c 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/commands/install.rs @@ -4,17 +4,12 @@ use clap::Parser; use futures_util::future; use node_semver::Version; use pacquet_diagnostics::tracing; -use pacquet_lockfile::{ - DependencyPath, Lockfile, PackageSnapshot, PkgName, PkgNameVerPeer, RootProjectSnapshot, -}; +use pacquet_lockfile::{Lockfile, PkgName, PkgNameVerPeer, RootProjectSnapshot}; use pacquet_package_json::DependencyGroup; -use pacquet_package_manager::{ - symlink_package, InstallPackageBySnapshot, InstallPackageFromRegistry, -}; +use pacquet_package_manager::{symlink_package, CreateVirtualStore, InstallPackageFromRegistry}; use pacquet_registry::PackageVersion; use pipe_trait::Pipe; use rayon::prelude::*; -use std::collections::HashMap; #[derive(Debug, Parser)] pub struct CliDependencyOptions { @@ -96,32 +91,6 @@ impl PackageManager { tracing::info!(target: "pacquet::install", node_modules = ?node_modules_path, "Complete subset"); } - /// Generate filesystem layout for the virtual store at `node_modules/.pacquet`. - async fn create_virtual_store( - &self, - packages: &Option>, - ) { - let Some(packages) = packages else { - todo!("check project_snapshot, error if it's not empty, do nothing if empty"); - }; - packages - .iter() - .map(|(dependency_path, package_snapshot)| async move { - InstallPackageBySnapshot { - tarball_cache: &self.tarball_cache, - http_client: &self.http_client, - config: self.config, - dependency_path, - package_snapshot, - } - .install() - .await - .unwrap(); // TODO: properly propagate this error - }) - .pipe(future::join_all) - .await; - } - /// Create symlinks for the direct dependencies. /// /// If package `foo@x.y.z` is declared as a dependency in `package.json`, @@ -202,7 +171,16 @@ impl PackageManager { "Non frozen lockfile is not yet supported", ); - self.create_virtual_store(packages).await; + CreateVirtualStore { + tarball_cache: &self.tarball_cache, + http_client: &self.http_client, + config: self.config, + packages: packages.as_ref(), + project_snapshot, + } + .create() + .await; + self.link_direct_dependencies(project_snapshot, args); } } diff --git a/crates/package_manager/Cargo.toml b/crates/package_manager/Cargo.toml index e53ac1a05..16fb9d69e 100644 --- a/crates/package_manager/Cargo.toml +++ b/crates/package_manager/Cargo.toml @@ -18,6 +18,7 @@ pacquet_registry = { workspace = true } pacquet_tarball = { workspace = true } derive_more = { workspace = true } +futures-util = { workspace = true } pipe-trait = { workspace = true } rayon = { workspace = true } reflink-copy = { workspace = true } diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index 817ccf735..d64aeefd9 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -5,6 +5,7 @@ mod link_file; mod symlink_layout; mod symlink_package; mod virtual_dir; +mod virtual_store; pub use cas::{create_cas_files, CreateCasFilesError}; pub use install_package_by_snapshot::{InstallPackageBySnapshot, InstallPackageBySnapshotError}; @@ -15,3 +16,4 @@ pub use link_file::{link_file, LinkFileError}; pub use symlink_layout::create_symlink_layout; pub use symlink_package::{symlink_package, SymlinkPackageError}; pub use virtual_dir::{CreateVirtualDirBySnapshot, CreateVirtualDirError}; +pub use virtual_store::CreateVirtualStore; diff --git a/crates/package_manager/src/virtual_store.rs b/crates/package_manager/src/virtual_store.rs new file mode 100644 index 000000000..ae983aabd --- /dev/null +++ b/crates/package_manager/src/virtual_store.rs @@ -0,0 +1,53 @@ +use crate::InstallPackageBySnapshot; +use futures_util::future; +use pacquet_lockfile::{DependencyPath, PackageSnapshot, RootProjectSnapshot}; +use pacquet_npmrc::Npmrc; +use pacquet_tarball::Cache; +use pipe_trait::Pipe; +use reqwest::Client; +use std::collections::HashMap; + +/// This subroutine generates filesystem layout for the virtual store at `node_modules/.pacquet`. +#[must_use] +pub struct CreateVirtualStore<'a> { + /// Shared cache that store downloaded tarballs. + pub tarball_cache: &'a Cache, + /// HTTP client to make HTTP requests. + pub http_client: &'a Client, + /// Configuration read from `.npmrc`. + pub config: &'static Npmrc, + /// The `packages` object from the lockfile. + pub packages: Option<&'a HashMap>, + /// The part of the lockfile that snapshots `package.json`. + pub project_snapshot: &'a RootProjectSnapshot, +} + +impl<'a> CreateVirtualStore<'a> { + /// Execute the subroutine. + pub async fn create(self) { + let CreateVirtualStore { tarball_cache, http_client, config, packages, project_snapshot } = + self; + + let packages = packages.unwrap_or_else(|| { + dbg!(project_snapshot); + todo!("check project_snapshot, error if it's not empty, do nothing if empty"); + }); + + packages + .iter() + .map(|(dependency_path, package_snapshot)| async move { + InstallPackageBySnapshot { + tarball_cache, + http_client, + config, + dependency_path, + package_snapshot, + } + .install() + .await + .unwrap(); // TODO: properly propagate this error + }) + .pipe(future::join_all) + .await; + } +} From ae3c114ae9b22acd9242853d264080ee67995699 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Thu, 12 Oct 2023 23:14:29 +0700 Subject: [PATCH 071/210] refactor: mod should have same name --- .../src/{cas.rs => create_cas_files.rs} | 0 ...ymlink_layout.rs => create_symlink_layout.rs} | 0 ..._dir.rs => create_virtual_dir_by_snapshot.rs} | 0 ...{virtual_store.rs => create_virtual_store.rs} | 0 crates/package_manager/src/lib.rs | 16 ++++++++-------- 5 files changed, 8 insertions(+), 8 deletions(-) rename crates/package_manager/src/{cas.rs => create_cas_files.rs} (100%) rename crates/package_manager/src/{symlink_layout.rs => create_symlink_layout.rs} (100%) rename crates/package_manager/src/{virtual_dir.rs => create_virtual_dir_by_snapshot.rs} (100%) rename crates/package_manager/src/{virtual_store.rs => create_virtual_store.rs} (100%) diff --git a/crates/package_manager/src/cas.rs b/crates/package_manager/src/create_cas_files.rs similarity index 100% rename from crates/package_manager/src/cas.rs rename to crates/package_manager/src/create_cas_files.rs diff --git a/crates/package_manager/src/symlink_layout.rs b/crates/package_manager/src/create_symlink_layout.rs similarity index 100% rename from crates/package_manager/src/symlink_layout.rs rename to crates/package_manager/src/create_symlink_layout.rs diff --git a/crates/package_manager/src/virtual_dir.rs b/crates/package_manager/src/create_virtual_dir_by_snapshot.rs similarity index 100% rename from crates/package_manager/src/virtual_dir.rs rename to crates/package_manager/src/create_virtual_dir_by_snapshot.rs diff --git a/crates/package_manager/src/virtual_store.rs b/crates/package_manager/src/create_virtual_store.rs similarity index 100% rename from crates/package_manager/src/virtual_store.rs rename to crates/package_manager/src/create_virtual_store.rs diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index d64aeefd9..32899e2ae 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -1,19 +1,19 @@ -mod cas; +mod create_cas_files; +mod create_symlink_layout; +mod create_virtual_dir_by_snapshot; +mod create_virtual_store; mod install_package_by_snapshot; mod install_package_from_registry; mod link_file; -mod symlink_layout; mod symlink_package; -mod virtual_dir; -mod virtual_store; -pub use cas::{create_cas_files, CreateCasFilesError}; +pub use create_cas_files::{create_cas_files, CreateCasFilesError}; +pub use create_symlink_layout::create_symlink_layout; +pub use create_virtual_dir_by_snapshot::{CreateVirtualDirBySnapshot, CreateVirtualDirError}; +pub use create_virtual_store::CreateVirtualStore; pub use install_package_by_snapshot::{InstallPackageBySnapshot, InstallPackageBySnapshotError}; pub use install_package_from_registry::{ InstallPackageFromRegistry, InstallPackageFromRegistryError, }; pub use link_file::{link_file, LinkFileError}; -pub use symlink_layout::create_symlink_layout; pub use symlink_package::{symlink_package, SymlinkPackageError}; -pub use virtual_dir::{CreateVirtualDirBySnapshot, CreateVirtualDirError}; -pub use virtual_store::CreateVirtualStore; From e2d2965c375495c8eaa45492caa5bf4ff2482db3 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 13 Oct 2023 01:17:36 +0700 Subject: [PATCH 072/210] refactor: move a function --- Cargo.lock | 1 + crates/cli/src/commands/install.rs | 54 ++++------------- crates/package_manager/Cargo.toml | 11 ++-- crates/package_manager/src/lib.rs | 2 + .../src/symlink_direct_dependencies.rs | 60 +++++++++++++++++++ 5 files changed, 79 insertions(+), 49 deletions(-) create mode 100644 crates/package_manager/src/symlink_direct_dependencies.rs diff --git a/Cargo.lock b/Cargo.lock index cdc739536..98b7fcf26 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1395,6 +1395,7 @@ dependencies = [ "pacquet_fs", "pacquet_lockfile", "pacquet_npmrc", + "pacquet_package_json", "pacquet_registry", "pacquet_tarball", "pipe-trait", diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/commands/install.rs index c23b2952c..d6d6c834d 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/commands/install.rs @@ -4,12 +4,13 @@ use clap::Parser; use futures_util::future; use node_semver::Version; use pacquet_diagnostics::tracing; -use pacquet_lockfile::{Lockfile, PkgName, PkgNameVerPeer, RootProjectSnapshot}; +use pacquet_lockfile::Lockfile; use pacquet_package_json::DependencyGroup; -use pacquet_package_manager::{symlink_package, CreateVirtualStore, InstallPackageFromRegistry}; +use pacquet_package_manager::{ + CreateVirtualStore, InstallPackageFromRegistry, SymlinkDirectDependencies, +}; use pacquet_registry::PackageVersion; use pipe_trait::Pipe; -use rayon::prelude::*; #[derive(Debug, Parser)] pub struct CliDependencyOptions { @@ -91,46 +92,6 @@ impl PackageManager { tracing::info!(target: "pacquet::install", node_modules = ?node_modules_path, "Complete subset"); } - /// Create symlinks for the direct dependencies. - /// - /// If package `foo@x.y.z` is declared as a dependency in `package.json`, - /// symlink `foo -> .pacquet/foo@x.y.z/node_modules/foo` shall be created - /// in the `node_modules` directory. - fn link_direct_dependencies( - &self, - project_snapshot: &RootProjectSnapshot, - args: &InstallCommandArgs, - ) { - let InstallCommandArgs { dependency_options, .. } = args; - - let RootProjectSnapshot::Single(project_snapshot) = project_snapshot else { - panic!("Monorepo is not yet supported"); - }; - - project_snapshot - .dependencies_by_groups(dependency_options.dependency_groups()) - .collect::>() - .par_iter() - .for_each(|(name, spec)| { - // TODO: the code below is not optimal - let virtual_store_name = - PkgNameVerPeer::new(PkgName::clone(name), spec.version.clone()) - .to_virtual_store_name(); - - let name_str = name.to_string(); - symlink_package( - &self - .config - .virtual_store_dir - .join(virtual_store_name) - .join("node_modules") - .join(&name_str), - &self.config.modules_dir.join(&name_str), - ) - .expect("symlink pkg"); // TODO: properly propagate this error - }); - } - /// Jobs of the `install` command. pub async fn install(&self, args: &InstallCommandArgs) -> Result<(), PackageManagerError> { let InstallCommandArgs { dependency_options, frozen_lockfile } = args; @@ -181,7 +142,12 @@ impl PackageManager { .create() .await; - self.link_direct_dependencies(project_snapshot, args); + SymlinkDirectDependencies { + config: self.config, + project_snapshot: &lockfile.project_snapshot, + dependency_groups: args.dependency_options.dependency_groups(), + } + .create(); } } diff --git a/crates/package_manager/Cargo.toml b/crates/package_manager/Cargo.toml index 16fb9d69e..227cd3343 100644 --- a/crates/package_manager/Cargo.toml +++ b/crates/package_manager/Cargo.toml @@ -11,11 +11,12 @@ license.workspace = true repository.workspace = true [dependencies] -pacquet_fs = { workspace = true } -pacquet_lockfile = { workspace = true } -pacquet_npmrc = { workspace = true } -pacquet_registry = { workspace = true } -pacquet_tarball = { workspace = true } +pacquet_fs = { workspace = true } +pacquet_lockfile = { workspace = true } +pacquet_npmrc = { workspace = true } +pacquet_package_json = { workspace = true } +pacquet_registry = { workspace = true } +pacquet_tarball = { workspace = true } derive_more = { workspace = true } futures-util = { workspace = true } diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index 32899e2ae..5a845b4a9 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -5,6 +5,7 @@ mod create_virtual_store; mod install_package_by_snapshot; mod install_package_from_registry; mod link_file; +mod symlink_direct_dependencies; mod symlink_package; pub use create_cas_files::{create_cas_files, CreateCasFilesError}; @@ -16,4 +17,5 @@ pub use install_package_from_registry::{ InstallPackageFromRegistry, InstallPackageFromRegistryError, }; pub use link_file::{link_file, LinkFileError}; +pub use symlink_direct_dependencies::SymlinkDirectDependencies; pub use symlink_package::{symlink_package, SymlinkPackageError}; diff --git a/crates/package_manager/src/symlink_direct_dependencies.rs b/crates/package_manager/src/symlink_direct_dependencies.rs new file mode 100644 index 000000000..00df6f112 --- /dev/null +++ b/crates/package_manager/src/symlink_direct_dependencies.rs @@ -0,0 +1,60 @@ +use crate::symlink_package; +use pacquet_lockfile::{PkgName, PkgNameVerPeer, RootProjectSnapshot}; +use pacquet_npmrc::Npmrc; +use pacquet_package_json::DependencyGroup; +use rayon::prelude::*; + +/// This subroutine creates symbolic links in the `node_modules` directory for +/// the direct dependencies. The targets of the link are the virtual directories. +/// +/// If package `foo@x.y.z` is declared as a dependency in `package.json`, +/// symlink `foo -> .pacquet/foo@x.y.z/node_modules/foo` shall be created +/// in the `node_modules` directory. +#[must_use] +pub struct SymlinkDirectDependencies<'a, DependencyGroupList> +where + DependencyGroupList: IntoIterator, +{ + /// Configuration read from `.npmrc`. + pub config: &'static Npmrc, + /// The part of the lockfile that snapshots `package.json`. + pub project_snapshot: &'a RootProjectSnapshot, + /// List of [`DependencyGroup`]s. + pub dependency_groups: DependencyGroupList, +} + +impl<'a, DependencyGroupList> SymlinkDirectDependencies<'a, DependencyGroupList> +where + DependencyGroupList: IntoIterator, +{ + /// Execute the subroutine. + pub fn create(self) { + let SymlinkDirectDependencies { config, project_snapshot, dependency_groups } = self; + + let RootProjectSnapshot::Single(project_snapshot) = project_snapshot else { + panic!("Monorepo is not yet supported"); // TODO: properly propagate this error + }; + + project_snapshot + .dependencies_by_groups(dependency_groups) + .collect::>() + .par_iter() + .for_each(|(name, spec)| { + // TODO: the code below is not optimal + let virtual_store_name = + PkgNameVerPeer::new(PkgName::clone(name), spec.version.clone()) + .to_virtual_store_name(); + + let name_str = name.to_string(); + symlink_package( + &config + .virtual_store_dir + .join(virtual_store_name) + .join("node_modules") + .join(&name_str), + &config.modules_dir.join(&name_str), + ) + .expect("symlink pkg"); // TODO: properly propagate this error + }); + } +} From cbe6b11f7577ec01803767adf01176d49009f6e4 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 13 Oct 2023 01:20:35 +0700 Subject: [PATCH 073/210] refactor: consistent method naming --- crates/cli/src/commands/add.rs | 6 +++--- crates/cli/src/commands/install.rs | 8 ++++---- .../package_manager/src/create_virtual_dir_by_snapshot.rs | 2 +- crates/package_manager/src/create_virtual_store.rs | 4 ++-- crates/package_manager/src/install_package_by_snapshot.rs | 4 ++-- .../package_manager/src/install_package_from_registry.rs | 4 ++-- crates/package_manager/src/symlink_direct_dependencies.rs | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/crates/cli/src/commands/add.rs b/crates/cli/src/commands/add.rs index a45f58c77..cf80850de 100644 --- a/crates/cli/src/commands/add.rs +++ b/crates/cli/src/commands/add.rs @@ -66,7 +66,7 @@ impl PackageManager { version_range: "latest", // TODO: add support for specifying tags node_modules_dir: &self.config.modules_dir, } - .install::() + .run::() .await .map_err(PackageManagerError::InstallPackageFromRegistry)?; let package_node_modules_path = self @@ -89,7 +89,7 @@ impl PackageManager { name, version_range: version, } - .install::() + .run::() .map_err(PackageManagerError::InstallPackageFromRegistry) }); @@ -115,7 +115,7 @@ impl PackageManager { name, version_range: version, } - .install::() + .run::() .map_err(PackageManagerError::InstallPackageFromRegistry) }, ); diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/commands/install.rs index d6d6c834d..3af060c53 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/commands/install.rs @@ -81,7 +81,7 @@ impl PackageManager { name, version_range, } - .install::() + .run::() .await .unwrap(); // TODO: proper error propagation self.install_dependencies_from_registry(&dependency).await; @@ -110,7 +110,7 @@ impl PackageManager { name, version_range, } - .install::() + .run::() .await .unwrap(); self.install_dependencies_from_registry(&dependency).await; @@ -139,7 +139,7 @@ impl PackageManager { packages: packages.as_ref(), project_snapshot, } - .create() + .run() .await; SymlinkDirectDependencies { @@ -147,7 +147,7 @@ impl PackageManager { project_snapshot: &lockfile.project_snapshot, dependency_groups: args.dependency_options.dependency_groups(), } - .create(); + .run(); } } diff --git a/crates/package_manager/src/create_virtual_dir_by_snapshot.rs b/crates/package_manager/src/create_virtual_dir_by_snapshot.rs index 9677b3feb..6ce98094c 100644 --- a/crates/package_manager/src/create_virtual_dir_by_snapshot.rs +++ b/crates/package_manager/src/create_virtual_dir_by_snapshot.rs @@ -42,7 +42,7 @@ pub struct CreateVirtualDirBySnapshot<'a> { impl<'a> CreateVirtualDirBySnapshot<'a> { /// Execute the subroutine. - pub fn create_virtual_dir_by_snapshot(self) -> Result<(), CreateVirtualDirError> { + pub fn run(self) -> Result<(), CreateVirtualDirError> { let CreateVirtualDirBySnapshot { virtual_store_dir, cas_paths, diff --git a/crates/package_manager/src/create_virtual_store.rs b/crates/package_manager/src/create_virtual_store.rs index ae983aabd..c632503b0 100644 --- a/crates/package_manager/src/create_virtual_store.rs +++ b/crates/package_manager/src/create_virtual_store.rs @@ -24,7 +24,7 @@ pub struct CreateVirtualStore<'a> { impl<'a> CreateVirtualStore<'a> { /// Execute the subroutine. - pub async fn create(self) { + pub async fn run(self) { let CreateVirtualStore { tarball_cache, http_client, config, packages, project_snapshot } = self; @@ -43,7 +43,7 @@ impl<'a> CreateVirtualStore<'a> { dependency_path, package_snapshot, } - .install() + .run() .await .unwrap(); // TODO: properly propagate this error }) diff --git a/crates/package_manager/src/install_package_by_snapshot.rs b/crates/package_manager/src/install_package_by_snapshot.rs index bc0b3b8b8..7422c969b 100644 --- a/crates/package_manager/src/install_package_by_snapshot.rs +++ b/crates/package_manager/src/install_package_by_snapshot.rs @@ -33,7 +33,7 @@ pub struct InstallPackageBySnapshot<'a> { impl<'a> InstallPackageBySnapshot<'a> { /// Execute the subroutine. - pub async fn install(self) -> Result<(), InstallPackageBySnapshotError> { + pub async fn run(self) -> Result<(), InstallPackageBySnapshotError> { let InstallPackageBySnapshot { tarball_cache, http_client, @@ -86,7 +86,7 @@ impl<'a> InstallPackageBySnapshot<'a> { dependency_path, package_snapshot, } - .create_virtual_dir_by_snapshot() + .run() .map_err(InstallPackageBySnapshotError::CreateVirtualDir)?; Ok(()) diff --git a/crates/package_manager/src/install_package_from_registry.rs b/crates/package_manager/src/install_package_from_registry.rs index 4edb11bf6..64ef42914 100644 --- a/crates/package_manager/src/install_package_from_registry.rs +++ b/crates/package_manager/src/install_package_from_registry.rs @@ -42,7 +42,7 @@ pub struct InstallPackageFromRegistry<'a> { impl<'a> InstallPackageFromRegistry<'a> { /// Execute the subroutine. - pub async fn install(self) -> Result + pub async fn run(self) -> Result where Tag: FromStr + Into, { @@ -165,7 +165,7 @@ mod tests { version_range: "1.0.0", node_modules_dir: node_modules_dir.path(), } - .install::() + .run::() .await .unwrap(); diff --git a/crates/package_manager/src/symlink_direct_dependencies.rs b/crates/package_manager/src/symlink_direct_dependencies.rs index 00df6f112..b9d42837b 100644 --- a/crates/package_manager/src/symlink_direct_dependencies.rs +++ b/crates/package_manager/src/symlink_direct_dependencies.rs @@ -28,7 +28,7 @@ where DependencyGroupList: IntoIterator, { /// Execute the subroutine. - pub fn create(self) { + pub fn run(self) { let SymlinkDirectDependencies { config, project_snapshot, dependency_groups } = self; let RootProjectSnapshot::Single(project_snapshot) = project_snapshot else { From 8b2bb8c33e40ac201af03742ec0db97c809687f6 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 13 Oct 2023 15:16:22 +0700 Subject: [PATCH 074/210] refactor: move a code section --- crates/cli/src/commands/install.rs | 30 ++++-------- .../src/install_frozen_lockfile.rs | 46 +++++++++++++++++++ crates/package_manager/src/lib.rs | 2 + 3 files changed, 56 insertions(+), 22 deletions(-) create mode 100644 crates/package_manager/src/install_frozen_lockfile.rs diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/commands/install.rs index 3af060c53..a94b83cf5 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/commands/install.rs @@ -6,9 +6,7 @@ use node_semver::Version; use pacquet_diagnostics::tracing; use pacquet_lockfile::Lockfile; use pacquet_package_json::DependencyGroup; -use pacquet_package_manager::{ - CreateVirtualStore, InstallPackageFromRegistry, SymlinkDirectDependencies, -}; +use pacquet_package_manager::{InstallFrozenLockfile, InstallPackageFromRegistry}; use pacquet_registry::PackageVersion; use pipe_trait::Pipe; @@ -125,29 +123,17 @@ impl PackageManager { let Lockfile { lockfile_version, project_snapshot, packages, .. } = lockfile; assert_eq!(lockfile_version.major, 6); // compatibility check already happens at serde, but this still helps preventing programmer mistakes. - // TODO: check if the lockfile is out-of-date - - assert!( - self.config.prefer_frozen_lockfile, - "Non frozen lockfile is not yet supported", - ); - - CreateVirtualStore { - tarball_cache: &self.tarball_cache, - http_client: &self.http_client, - config: self.config, - packages: packages.as_ref(), + let PackageManager { config, http_client, tarball_cache, .. } = self; + InstallFrozenLockfile { + tarball_cache, + http_client, + config, project_snapshot, + packages: packages.as_ref(), + dependency_groups: args.dependency_options.dependency_groups(), } .run() .await; - - SymlinkDirectDependencies { - config: self.config, - project_snapshot: &lockfile.project_snapshot, - dependency_groups: args.dependency_options.dependency_groups(), - } - .run(); } } diff --git a/crates/package_manager/src/install_frozen_lockfile.rs b/crates/package_manager/src/install_frozen_lockfile.rs new file mode 100644 index 000000000..a25dac57b --- /dev/null +++ b/crates/package_manager/src/install_frozen_lockfile.rs @@ -0,0 +1,46 @@ +use crate::{CreateVirtualStore, SymlinkDirectDependencies}; +use pacquet_lockfile::{DependencyPath, PackageSnapshot, RootProjectSnapshot}; +use pacquet_npmrc::Npmrc; +use pacquet_package_json::DependencyGroup; +use pacquet_tarball::Cache; +use reqwest::Client; +use std::collections::HashMap; + +#[must_use] +pub struct InstallFrozenLockfile<'a, DependencyGroupList> +where + DependencyGroupList: IntoIterator, +{ + pub tarball_cache: &'a Cache, + pub http_client: &'a Client, + pub config: &'static Npmrc, + pub project_snapshot: &'a RootProjectSnapshot, + pub packages: Option<&'a HashMap>, + pub dependency_groups: DependencyGroupList, +} + +impl<'a, DependencyGroupList> InstallFrozenLockfile<'a, DependencyGroupList> +where + DependencyGroupList: IntoIterator, +{ + pub async fn run(self) { + let InstallFrozenLockfile { + tarball_cache, + http_client, + config, + project_snapshot, + packages, + dependency_groups, + } = self; + + // TODO: check if the lockfile is out-of-date + + assert!(config.prefer_frozen_lockfile, "Non frozen lockfile is not yet supported"); + + CreateVirtualStore { tarball_cache, http_client, config, packages, project_snapshot } + .run() + .await; + + SymlinkDirectDependencies { config, project_snapshot, dependency_groups }.run(); + } +} diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index 5a845b4a9..f8fcdbd8e 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -2,6 +2,7 @@ mod create_cas_files; mod create_symlink_layout; mod create_virtual_dir_by_snapshot; mod create_virtual_store; +mod install_frozen_lockfile; mod install_package_by_snapshot; mod install_package_from_registry; mod link_file; @@ -12,6 +13,7 @@ pub use create_cas_files::{create_cas_files, CreateCasFilesError}; pub use create_symlink_layout::create_symlink_layout; pub use create_virtual_dir_by_snapshot::{CreateVirtualDirBySnapshot, CreateVirtualDirError}; pub use create_virtual_store::CreateVirtualStore; +pub use install_frozen_lockfile::InstallFrozenLockfile; pub use install_package_by_snapshot::{InstallPackageBySnapshot, InstallPackageBySnapshotError}; pub use install_package_from_registry::{ InstallPackageFromRegistry, InstallPackageFromRegistryError, From daecbfdbcbf4623a3a3d91ecea4993b4be81eac6 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 13 Oct 2023 15:27:35 +0700 Subject: [PATCH 075/210] docs: InstallFrozenLockfile --- crates/package_manager/src/install_frozen_lockfile.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/package_manager/src/install_frozen_lockfile.rs b/crates/package_manager/src/install_frozen_lockfile.rs index a25dac57b..bc909c18b 100644 --- a/crates/package_manager/src/install_frozen_lockfile.rs +++ b/crates/package_manager/src/install_frozen_lockfile.rs @@ -6,16 +6,23 @@ use pacquet_tarball::Cache; use reqwest::Client; use std::collections::HashMap; +/// This subroutine installs dependencies from a frozen lockfile. #[must_use] pub struct InstallFrozenLockfile<'a, DependencyGroupList> where DependencyGroupList: IntoIterator, { + /// Shared cache that store downloaded tarballs. pub tarball_cache: &'a Cache, + /// HTTP client to make HTTP requests. pub http_client: &'a Client, + /// Configuration read from `.npmrc`. pub config: &'static Npmrc, + /// The part of the lockfile that snapshots `package.json`. pub project_snapshot: &'a RootProjectSnapshot, + /// The `packages` object from the lockfile. pub packages: Option<&'a HashMap>, + /// List of [`DependencyGroup`]s. pub dependency_groups: DependencyGroupList, } @@ -23,6 +30,7 @@ impl<'a, DependencyGroupList> InstallFrozenLockfile<'a, DependencyGroupList> where DependencyGroupList: IntoIterator, { + /// Execute the subroutine. pub async fn run(self) { let InstallFrozenLockfile { tarball_cache, From 5bdeeb6dbd982e0c4a319252405633b5ff1e235d Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 13 Oct 2023 15:29:04 +0700 Subject: [PATCH 076/210] refactor: star export --- crates/lockfile/src/lib.rs | 34 +++++++++++++++---------------- crates/package_manager/src/lib.rs | 22 +++++++++----------- 2 files changed, 26 insertions(+), 30 deletions(-) diff --git a/crates/lockfile/src/lib.rs b/crates/lockfile/src/lib.rs index e962975f8..2c2683ec4 100644 --- a/crates/lockfile/src/lib.rs +++ b/crates/lockfile/src/lib.rs @@ -15,24 +15,22 @@ mod resolution; mod resolved_dependency; mod root_project_snapshot; -pub use comver::{ComVer, ParseComVerError}; -pub use dependency_path::DependencyPath; -pub use load_lockfile::LoadLockfileError; -pub use lockfile_version::LockfileVersion; -pub use multi_project_snapshot::MultiProjectSnapshot; -pub use package_snapshot::{LockfilePeerDependencyMetaValue, PackageSnapshot}; -pub use package_snapshot_dependency::PackageSnapshotDependency; -pub use pkg_name::{ParsePkgNameError, PkgName}; -pub use pkg_name_suffix::{ParsePkgNameSuffixError, PkgNameSuffix}; -pub use pkg_name_ver::{ParsePkgNameVerError, PkgNameVer}; -pub use pkg_name_ver_peer::{ParsePkgNameVerPeerError, PkgNameVerPeer}; -pub use pkg_ver_peer::{ParsePkgVerPeerError, PkgVerPeer}; -pub use project_snapshot::ProjectSnapshot; -pub use resolution::{ - DirectoryResolution, GitResolution, LockfileResolution, RegistryResolution, TarballResolution, -}; -pub use resolved_dependency::{ResolvedDependencyMap, ResolvedDependencySpec}; -pub use root_project_snapshot::RootProjectSnapshot; +pub use comver::*; +pub use dependency_path::*; +pub use load_lockfile::*; +pub use lockfile_version::*; +pub use multi_project_snapshot::*; +pub use package_snapshot::*; +pub use package_snapshot_dependency::*; +pub use pkg_name::*; +pub use pkg_name_suffix::*; +pub use pkg_name_ver::*; +pub use pkg_name_ver_peer::*; +pub use pkg_ver_peer::*; +pub use project_snapshot::*; +pub use resolution::*; +pub use resolved_dependency::*; +pub use root_project_snapshot::*; use serde::{Deserialize, Serialize}; use std::collections::HashMap; diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index f8fcdbd8e..3263a8832 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -9,15 +9,13 @@ mod link_file; mod symlink_direct_dependencies; mod symlink_package; -pub use create_cas_files::{create_cas_files, CreateCasFilesError}; -pub use create_symlink_layout::create_symlink_layout; -pub use create_virtual_dir_by_snapshot::{CreateVirtualDirBySnapshot, CreateVirtualDirError}; -pub use create_virtual_store::CreateVirtualStore; -pub use install_frozen_lockfile::InstallFrozenLockfile; -pub use install_package_by_snapshot::{InstallPackageBySnapshot, InstallPackageBySnapshotError}; -pub use install_package_from_registry::{ - InstallPackageFromRegistry, InstallPackageFromRegistryError, -}; -pub use link_file::{link_file, LinkFileError}; -pub use symlink_direct_dependencies::SymlinkDirectDependencies; -pub use symlink_package::{symlink_package, SymlinkPackageError}; +pub use create_cas_files::*; +pub use create_symlink_layout::*; +pub use create_virtual_dir_by_snapshot::*; +pub use create_virtual_store::*; +pub use install_frozen_lockfile::*; +pub use install_package_by_snapshot::*; +pub use install_package_from_registry::*; +pub use link_file::*; +pub use symlink_direct_dependencies::*; +pub use symlink_package::*; From edcf147a1221808966f25ba9c55cfa4005c9d573 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 13 Oct 2023 17:01:02 +0700 Subject: [PATCH 077/210] refactor: destructure --- crates/cli/src/commands/install.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/commands/install.rs index a94b83cf5..5a42f01bb 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/commands/install.rs @@ -92,19 +92,20 @@ impl PackageManager { /// Jobs of the `install` command. pub async fn install(&self, args: &InstallCommandArgs) -> Result<(), PackageManagerError> { + let PackageManager { config, http_client, tarball_cache, lockfile, package_json } = self; let InstallCommandArgs { dependency_options, frozen_lockfile } = args; tracing::info!(target: "pacquet::install", "Start all"); - match (self.config.lockfile, frozen_lockfile, &self.lockfile) { + match (config.lockfile, frozen_lockfile, lockfile) { (false, _, _) => { - self.package_json + package_json .dependencies(dependency_options.dependency_groups()) .map(|(name, version_range)| async move { let dependency = InstallPackageFromRegistry { - tarball_cache: &self.tarball_cache, - http_client: &self.http_client, - config: self.config, - node_modules_dir: &self.config.modules_dir, + tarball_cache, + http_client, + config, + node_modules_dir: &config.modules_dir, name, version_range, } @@ -123,7 +124,6 @@ impl PackageManager { let Lockfile { lockfile_version, project_snapshot, packages, .. } = lockfile; assert_eq!(lockfile_version.major, 6); // compatibility check already happens at serde, but this still helps preventing programmer mistakes. - let PackageManager { config, http_client, tarball_cache, .. } = self; InstallFrozenLockfile { tarball_cache, http_client, From 2a2787f4a89650baa59a77727e84188e21de1a4f Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 13 Oct 2023 17:29:45 +0700 Subject: [PATCH 078/210] refactor: InstallWithoutLockfile --- Cargo.lock | 1 + crates/cli/src/commands/install.rs | 69 ++---------- crates/package_manager/Cargo.toml | 18 +-- .../src/install_without_lockfile.rs | 106 ++++++++++++++++++ crates/package_manager/src/lib.rs | 2 + 5 files changed, 129 insertions(+), 67 deletions(-) create mode 100644 crates/package_manager/src/install_without_lockfile.rs diff --git a/Cargo.lock b/Cargo.lock index 98b7fcf26..9593489fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1388,6 +1388,7 @@ dependencies = [ name = "pacquet_package_manager" version = "0.0.1" dependencies = [ + "async-recursion", "derive_more", "futures-util", "miette", diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/commands/install.rs index 5a42f01bb..0631c30ed 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/commands/install.rs @@ -1,14 +1,9 @@ use crate::package_manager::{PackageManager, PackageManagerError}; -use async_recursion::async_recursion; use clap::Parser; -use futures_util::future; -use node_semver::Version; use pacquet_diagnostics::tracing; use pacquet_lockfile::Lockfile; use pacquet_package_json::DependencyGroup; -use pacquet_package_manager::{InstallFrozenLockfile, InstallPackageFromRegistry}; -use pacquet_registry::PackageVersion; -use pipe_trait::Pipe; +use pacquet_package_manager::{InstallFrozenLockfile, InstallWithoutLockfile}; #[derive(Debug, Parser)] pub struct CliDependencyOptions { @@ -55,41 +50,6 @@ pub struct InstallCommandArgs { } impl PackageManager { - /// Install dependencies of a dependency. - /// - /// This function is used by [`PackageManager::install`] without a lockfile. - #[async_recursion] - async fn install_dependencies_from_registry(&self, package: &PackageVersion) { - let node_modules_path = self - .config - .virtual_store_dir - .join(package.to_virtual_store_name()) - .join("node_modules"); - - tracing::info!(target: "pacquet::install", node_modules = ?node_modules_path, "Start subset"); - - package - .dependencies(self.config.auto_install_peers) - .map(|(name, version_range)| async { - let dependency = InstallPackageFromRegistry { - tarball_cache: &self.tarball_cache, - http_client: &self.http_client, - config: self.config, - node_modules_dir: &node_modules_path, - name, - version_range, - } - .run::() - .await - .unwrap(); // TODO: proper error propagation - self.install_dependencies_from_registry(&dependency).await; - }) - .pipe(future::join_all) - .await; - - tracing::info!(target: "pacquet::install", node_modules = ?node_modules_path, "Complete subset"); - } - /// Jobs of the `install` command. pub async fn install(&self, args: &InstallCommandArgs) -> Result<(), PackageManagerError> { let PackageManager { config, http_client, tarball_cache, lockfile, package_json } = self; @@ -98,24 +58,15 @@ impl PackageManager { match (config.lockfile, frozen_lockfile, lockfile) { (false, _, _) => { - package_json - .dependencies(dependency_options.dependency_groups()) - .map(|(name, version_range)| async move { - let dependency = InstallPackageFromRegistry { - tarball_cache, - http_client, - config, - node_modules_dir: &config.modules_dir, - name, - version_range, - } - .run::() - .await - .unwrap(); - self.install_dependencies_from_registry(&dependency).await; - }) - .pipe(future::join_all) - .await; + InstallWithoutLockfile { + tarball_cache, + http_client, + config, + package_json, + dependency_groups: dependency_options.dependency_groups(), + } + .run() + .await; } (true, false, Some(_)) | (true, false, None) | (true, true, None) => { unimplemented!(); diff --git a/crates/package_manager/Cargo.toml b/crates/package_manager/Cargo.toml index 227cd3343..66ad853d9 100644 --- a/crates/package_manager/Cargo.toml +++ b/crates/package_manager/Cargo.toml @@ -18,14 +18,16 @@ pacquet_package_json = { workspace = true } pacquet_registry = { workspace = true } pacquet_tarball = { workspace = true } -derive_more = { workspace = true } -futures-util = { workspace = true } -pipe-trait = { workspace = true } -rayon = { workspace = true } -reflink-copy = { workspace = true } -reqwest = { workspace = true } -tracing = { workspace = true } -miette = { workspace = true } +async-recursion = { workspace = true } +derive_more = { workspace = true } +futures-util = { workspace = true } +node-semver = { workspace = true } +pipe-trait = { workspace = true } +rayon = { workspace = true } +reflink-copy = { workspace = true } +reqwest = { workspace = true } +tracing = { workspace = true } +miette = { workspace = true } [dev-dependencies] node-semver = { workspace = true } diff --git a/crates/package_manager/src/install_without_lockfile.rs b/crates/package_manager/src/install_without_lockfile.rs new file mode 100644 index 000000000..aae24daaa --- /dev/null +++ b/crates/package_manager/src/install_without_lockfile.rs @@ -0,0 +1,106 @@ +use crate::InstallPackageFromRegistry; +use async_recursion::async_recursion; +use futures_util::future; +use node_semver::Version; +use pacquet_npmrc::Npmrc; +use pacquet_package_json::{DependencyGroup, PackageJson}; +use pacquet_registry::PackageVersion; +use pacquet_tarball::Cache; +use pipe_trait::Pipe; +use reqwest::Client; + +/// This subroutine install packages from a `package.json` without reading or writing a lockfile. +#[must_use] +pub struct InstallWithoutLockfile<'a, DependencyGroupList> { + /// Shared cache that store downloaded tarballs. + pub tarball_cache: &'a Cache, + /// HTTP client to make HTTP requests. + pub http_client: &'a Client, + /// Configuration read from `.npmrc`. + pub config: &'static Npmrc, + /// Data from the `package.json` file. + pub package_json: &'a PackageJson, + /// List of [`DependencyGroup`]s. + pub dependency_groups: DependencyGroupList, +} + +impl<'a, DependencyGroupList> InstallWithoutLockfile<'a, DependencyGroupList> { + /// Execute the subroutine. + pub async fn run(self) + where + DependencyGroupList: IntoIterator, + { + let InstallWithoutLockfile { + tarball_cache, + http_client, + config, + package_json, + dependency_groups, + } = self; + + let _: Vec<()> = package_json + .dependencies(dependency_groups.into_iter()) + .map(|(name, version_range)| async move { + let dependency = InstallPackageFromRegistry { + tarball_cache, + http_client, + config, + node_modules_dir: &config.modules_dir, + name, + version_range, + } + .run::() + .await + .unwrap(); + + InstallWithoutLockfile { + tarball_cache, + http_client, + config, + package_json, + dependency_groups: (), + } + .install_dependencies_from_registry(&dependency) + .await; + }) + .pipe(future::join_all) + .await; + } +} + +impl<'a> InstallWithoutLockfile<'a, ()> { + /// Install dependencies of a dependency. + #[async_recursion] + async fn install_dependencies_from_registry(&self, package: &PackageVersion) { + let InstallWithoutLockfile { tarball_cache, http_client, config, .. } = self; + + let node_modules_path = self + .config + .virtual_store_dir + .join(package.to_virtual_store_name()) + .join("node_modules"); + + tracing::info!(target: "pacquet::install", node_modules = ?node_modules_path, "Start subset"); + + package + .dependencies(self.config.auto_install_peers) + .map(|(name, version_range)| async { + let dependency = InstallPackageFromRegistry { + tarball_cache, + http_client, + config, + node_modules_dir: &node_modules_path, + name, + version_range, + } + .run::() + .await + .unwrap(); // TODO: proper error propagation + self.install_dependencies_from_registry(&dependency).await; + }) + .pipe(future::join_all) + .await; + + tracing::info!(target: "pacquet::install", node_modules = ?node_modules_path, "Complete subset"); + } +} diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index 3263a8832..080086e81 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -5,6 +5,7 @@ mod create_virtual_store; mod install_frozen_lockfile; mod install_package_by_snapshot; mod install_package_from_registry; +mod install_without_lockfile; mod link_file; mod symlink_direct_dependencies; mod symlink_package; @@ -16,6 +17,7 @@ pub use create_virtual_store::*; pub use install_frozen_lockfile::*; pub use install_package_by_snapshot::*; pub use install_package_from_registry::*; +pub use install_without_lockfile::*; pub use link_file::*; pub use symlink_direct_dependencies::*; pub use symlink_package::*; From 54445c6ccc4c76362c4de6749b72119f6fe57a61 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 13 Oct 2023 17:42:52 +0700 Subject: [PATCH 079/210] refactor(test): remove unnecessary tempdir --- crates/package_manager/src/install_package_from_registry.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/package_manager/src/install_package_from_registry.rs b/crates/package_manager/src/install_package_from_registry.rs index 64ef42914..708c33be1 100644 --- a/crates/package_manager/src/install_package_from_registry.rs +++ b/crates/package_manager/src/install_package_from_registry.rs @@ -156,14 +156,13 @@ mod tests { .pipe(Box::new) .pipe(Box::leak); let http_client = reqwest::Client::new(); - let node_modules_dir = tempdir().unwrap(); let package = InstallPackageFromRegistry { tarball_cache: &Default::default(), config, http_client: &http_client, name: "fast-querystring", version_range: "1.0.0", - node_modules_dir: node_modules_dir.path(), + node_modules_dir: modules_dir.path(), } .run::() .await @@ -184,7 +183,7 @@ mod tests { // Make sure the symlink is resolving to the correct path assert_eq!( - fs::read_link(node_modules_dir.path().join(&package.name)).unwrap(), + fs::read_link(modules_dir.path().join(&package.name)).unwrap(), virtual_store_path ); } From 1625a231d90a1d5a6e691bb15c323b226bb32f4d Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 13 Oct 2023 18:46:59 +0700 Subject: [PATCH 080/210] refactor: reuse --- crates/cli/src/commands/install.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/commands/install.rs index 0631c30ed..237691916 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/commands/install.rs @@ -81,7 +81,7 @@ impl PackageManager { config, project_snapshot, packages: packages.as_ref(), - dependency_groups: args.dependency_options.dependency_groups(), + dependency_groups: dependency_options.dependency_groups(), } .run() .await; From e6a7268fdec8bc03109cbf59e2d38db72ad94567 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 13 Oct 2023 18:52:05 +0700 Subject: [PATCH 081/210] refactor: remove fake mut --- crates/package_json/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/package_json/src/lib.rs b/crates/package_json/src/lib.rs index d72765e22..cbd5e8eb1 100644 --- a/crates/package_json/src/lib.rs +++ b/crates/package_json/src/lib.rs @@ -128,7 +128,7 @@ impl PackageJson { Ok(PackageJson { path, value }) } - pub fn save(&mut self) -> Result<(), PackageJsonError> { + pub fn save(&self) -> Result<(), PackageJsonError> { let mut file = fs::File::create(&self.path)?; let contents = serde_json::to_string_pretty(&self.value)?; file.write_all(contents.as_bytes())?; From 2999bf9df5440dc88de2278d99fe02016881a880 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 13 Oct 2023 19:41:10 +0700 Subject: [PATCH 082/210] refactor: move code from install --- crates/cli/src/commands/install.rs | 48 ++++------------ crates/package_manager/src/install.rs | 82 +++++++++++++++++++++++++++ crates/package_manager/src/lib.rs | 2 + 3 files changed, 96 insertions(+), 36 deletions(-) create mode 100644 crates/package_manager/src/install.rs diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/commands/install.rs index 237691916..97a623948 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/commands/install.rs @@ -1,9 +1,7 @@ use crate::package_manager::{PackageManager, PackageManagerError}; use clap::Parser; -use pacquet_diagnostics::tracing; -use pacquet_lockfile::Lockfile; use pacquet_package_json::DependencyGroup; -use pacquet_package_manager::{InstallFrozenLockfile, InstallWithoutLockfile}; +use pacquet_package_manager::Install; #[derive(Debug, Parser)] pub struct CliDependencyOptions { @@ -54,41 +52,19 @@ impl PackageManager { pub async fn install(&self, args: &InstallCommandArgs) -> Result<(), PackageManagerError> { let PackageManager { config, http_client, tarball_cache, lockfile, package_json } = self; let InstallCommandArgs { dependency_options, frozen_lockfile } = args; - tracing::info!(target: "pacquet::install", "Start all"); - - match (config.lockfile, frozen_lockfile, lockfile) { - (false, _, _) => { - InstallWithoutLockfile { - tarball_cache, - http_client, - config, - package_json, - dependency_groups: dependency_options.dependency_groups(), - } - .run() - .await; - } - (true, false, Some(_)) | (true, false, None) | (true, true, None) => { - unimplemented!(); - } - (true, true, Some(lockfile)) => { - let Lockfile { lockfile_version, project_snapshot, packages, .. } = lockfile; - assert_eq!(lockfile_version.major, 6); // compatibility check already happens at serde, but this still helps preventing programmer mistakes. - - InstallFrozenLockfile { - tarball_cache, - http_client, - config, - project_snapshot, - packages: packages.as_ref(), - dependency_groups: dependency_options.dependency_groups(), - } - .run() - .await; - } + + Install { + tarball_cache, + http_client, + config, + package_json, + lockfile: lockfile.as_ref(), + dependency_groups: dependency_options.dependency_groups(), + frozen_lockfile: *frozen_lockfile, } + .run() + .await; - tracing::info!(target: "pacquet::install", "Complete all"); Ok(()) } } diff --git a/crates/package_manager/src/install.rs b/crates/package_manager/src/install.rs new file mode 100644 index 000000000..779d6fe7a --- /dev/null +++ b/crates/package_manager/src/install.rs @@ -0,0 +1,82 @@ +use crate::{InstallFrozenLockfile, InstallWithoutLockfile}; +use pacquet_lockfile::Lockfile; +use pacquet_npmrc::Npmrc; +use pacquet_package_json::{DependencyGroup, PackageJson}; +use pacquet_tarball::Cache; +use reqwest::Client; + +/// This subroutine does everything `pacquet install` is supposed to do. +#[must_use] +pub struct Install<'a, DependencyGroupList> +where + DependencyGroupList: IntoIterator, +{ + /// Shared cache that store downloaded tarballs. + pub tarball_cache: &'a Cache, + /// HTTP client to make HTTP requests. + pub http_client: &'a Client, + /// Configuration read from `.npmrc`. + pub config: &'static Npmrc, + /// Data from the `package.json` file. + pub package_json: &'a PackageJson, + /// Data from the `pnpm-lock.yaml` file. + pub lockfile: Option<&'a Lockfile>, + /// List of [`DependencyGroup`]s. + pub dependency_groups: DependencyGroupList, + /// Whether `--frozen-lockfile` is specified. + pub frozen_lockfile: bool, +} + +impl<'a, DependencyGroupList> Install<'a, DependencyGroupList> +where + DependencyGroupList: IntoIterator, +{ + /// Execute the subroutine. + pub async fn run(self) { + let Install { + tarball_cache, + http_client, + config, + package_json, + lockfile, + dependency_groups, + frozen_lockfile, + } = self; + + tracing::info!(target: "pacquet::install", "Start all"); + + match (config.lockfile, frozen_lockfile, lockfile) { + (false, _, _) => { + InstallWithoutLockfile { + tarball_cache, + http_client, + config, + package_json, + dependency_groups, + } + .run() + .await; + } + (true, false, Some(_)) | (true, false, None) | (true, true, None) => { + unimplemented!(); + } + (true, true, Some(lockfile)) => { + let Lockfile { lockfile_version, project_snapshot, packages, .. } = lockfile; + assert_eq!(lockfile_version.major, 6); // compatibility check already happens at serde, but this still helps preventing programmer mistakes. + + InstallFrozenLockfile { + tarball_cache, + http_client, + config, + project_snapshot, + packages: packages.as_ref(), + dependency_groups, + } + .run() + .await; + } + } + + tracing::info!(target: "pacquet::install", "Complete all"); + } +} diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index 080086e81..18290c000 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -2,6 +2,7 @@ mod create_cas_files; mod create_symlink_layout; mod create_virtual_dir_by_snapshot; mod create_virtual_store; +mod install; mod install_frozen_lockfile; mod install_package_by_snapshot; mod install_package_from_registry; @@ -14,6 +15,7 @@ pub use create_cas_files::*; pub use create_symlink_layout::*; pub use create_virtual_dir_by_snapshot::*; pub use create_virtual_store::*; +pub use install::*; pub use install_frozen_lockfile::*; pub use install_package_by_snapshot::*; pub use install_package_from_registry::*; From 742a6e24b0d3100cf27c4aa90ad9cad359fdcdf6 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 13 Oct 2023 20:13:06 +0700 Subject: [PATCH 083/210] refactor(test): move --- Cargo.lock | 2 + crates/cli/src/commands/install.rs | 64 +---------- crates/package_manager/Cargo.toml | 2 + crates/package_manager/src/install.rs | 106 ++++++++++++++++++ ...sts__should_install_dependencies.snap.tmp} | 0 ...l__tests__should_install_dependencies.snap | 21 ++++ 6 files changed, 133 insertions(+), 62 deletions(-) rename crates/{cli/src/commands/snapshots/pacquet_cli__commands__install__tests__should_install_dependencies.snap => package_manager/src/pacquet_cli__commands__install__tests__should_install_dependencies.snap.tmp} (100%) create mode 100644 crates/package_manager/src/snapshots/pacquet_package_manager__install__tests__should_install_dependencies.snap diff --git a/Cargo.lock b/Cargo.lock index 9593489fa..2b3818f8c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1391,6 +1391,7 @@ dependencies = [ "async-recursion", "derive_more", "futures-util", + "insta", "miette", "node-semver", "pacquet_fs", @@ -1407,6 +1408,7 @@ dependencies = [ "tempfile", "tokio", "tracing", + "walkdir", ] [[package]] diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/commands/install.rs index 97a623948..f2f93e96e 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/commands/install.rs @@ -71,25 +71,9 @@ impl PackageManager { #[cfg(test)] mod tests { - use std::env; - use std::io::Result; - - use crate::commands::install::{CliDependencyOptions, InstallCommandArgs}; - use crate::fs::get_all_folders; - use crate::package_manager::PackageManager; - use pacquet_npmrc::Npmrc; - use pacquet_package_json::{DependencyGroup, PackageJson}; + use crate::commands::install::CliDependencyOptions; + use pacquet_package_json::DependencyGroup; use pretty_assertions::assert_eq; - use tempfile::tempdir; - - // Helper function to check if a path is a symlink or junction - fn is_symlink_or_junction(path: std::path::PathBuf) -> Result { - #[cfg(windows)] - return junction::exists(&path); - - #[cfg(not(windows))] - return Ok(path.is_symlink()); - } #[test] fn install_args_to_dependency_groups() { @@ -144,48 +128,4 @@ mod tests { [Default, Dev], ); } - - #[tokio::test] - pub async fn should_install_dependencies() { - let dir = tempdir().unwrap(); - let current_directory = env::current_dir().unwrap(); - env::set_current_dir(dir.path()).unwrap(); - - let package_json_path = dir.path().join("package.json"); - let mut package_json = PackageJson::create_if_needed(package_json_path.clone()).unwrap(); - - package_json.add_dependency("is-odd", "3.0.1", DependencyGroup::Default).unwrap(); - package_json - .add_dependency("fast-decode-uri-component", "1.0.1", DependencyGroup::Dev) - .unwrap(); - - package_json.save().unwrap(); - - let package_manager = - PackageManager::new(&package_json_path, Npmrc::current().leak()).unwrap(); - let args = InstallCommandArgs { - dependency_options: CliDependencyOptions { - prod: false, - dev: false, - no_optional: false, - }, - frozen_lockfile: false, - }; - package_manager.install(&args).await.unwrap(); - - // Make sure the package is installed - assert!(is_symlink_or_junction(dir.path().join("node_modules/is-odd")).unwrap()); - assert!(dir.path().join("node_modules/.pacquet/is-odd@3.0.1").exists()); - // Make sure it installs direct dependencies - assert!(!dir.path().join("node_modules/is-number").exists()); - assert!(dir.path().join("node_modules/.pacquet/is-number@6.0.0").exists()); - // Make sure we install dev-dependencies as well - assert!(is_symlink_or_junction(dir.path().join("node_modules/fast-decode-uri-component")) - .unwrap()); - assert!(dir.path().join("node_modules/.pacquet/fast-decode-uri-component@1.0.1").is_dir()); - - insta::assert_debug_snapshot!(get_all_folders(dir.path())); - - env::set_current_dir(¤t_directory).unwrap(); - } } diff --git a/crates/package_manager/Cargo.toml b/crates/package_manager/Cargo.toml index 66ad853d9..3bf3c64d9 100644 --- a/crates/package_manager/Cargo.toml +++ b/crates/package_manager/Cargo.toml @@ -31,6 +31,8 @@ miette = { workspace = true } [dev-dependencies] node-semver = { workspace = true } +insta = { workspace = true } pretty_assertions = { workspace = true } tempfile = { workspace = true } tokio = { workspace = true } +walkdir = { workspace = true } diff --git a/crates/package_manager/src/install.rs b/crates/package_manager/src/install.rs index 779d6fe7a..c99044430 100644 --- a/crates/package_manager/src/install.rs +++ b/crates/package_manager/src/install.rs @@ -80,3 +80,109 @@ where tracing::info!(target: "pacquet::install", "Complete all"); } } + +#[cfg(test)] +mod tests { + use super::*; + use pacquet_npmrc::Npmrc; + use pacquet_package_json::{DependencyGroup, PackageJson}; + use std::{env, io}; + use tempfile::tempdir; + + // Helper function to check if a path is a symlink or junction + fn is_symlink_or_junction(path: std::path::PathBuf) -> io::Result { + #[cfg(windows)] + return junction::exists(&path); + + #[cfg(not(windows))] + return Ok(path.is_symlink()); + } + + pub fn get_all_folders(root: &std::path::Path) -> Vec { + let mut files = Vec::new(); + for entry in walkdir::WalkDir::new(root) { + let entry = entry.unwrap(); + let entry_path = entry.path(); + if entry.file_type().is_dir() || entry.file_type().is_symlink() { + // We need this mutation to ensure that both Unix and Windows paths resolves the same. + // TODO: Find a better way to do this? + let simple_path = entry_path + .strip_prefix(root) + .unwrap() + .components() + .map(|c| c.as_os_str().to_str().expect("invalid UTF-8")) + .collect::>() + .join("/"); + + if !simple_path.is_empty() { + files.push(simple_path); + } + } + } + files.sort(); + files + } + + #[tokio::test] + pub async fn should_install_dependencies() { + let dir = tempdir().unwrap(); + let store_dir = dir.path().join("pacquet-store"); + let project_root = dir.path().join("project"); + let modules_dir = project_root.join("node_modules"); // TODO: we shouldn't have to define this + let virtual_store_dir = modules_dir.join(".pacquet"); // TODO: we shouldn't have to define this + + // let current_directory = env::current_dir().unwrap(); + // env::set_current_dir(dir.path()).unwrap(); + + let package_json_path = dir.path().join("package.json"); + let mut package_json = PackageJson::create_if_needed(package_json_path.clone()).unwrap(); + + package_json.add_dependency("is-odd", "3.0.1", DependencyGroup::Default).unwrap(); + package_json + .add_dependency("fast-decode-uri-component", "1.0.1", DependencyGroup::Dev) + .unwrap(); + + package_json.save().unwrap(); + + let mut config = Npmrc::new(); + config.store_dir = store_dir.to_path_buf(); + config.modules_dir = modules_dir.to_path_buf(); + config.virtual_store_dir = virtual_store_dir.to_path_buf(); + let config = config.leak(); + + Install { + tarball_cache: &Default::default(), + http_client: &Default::default(), + config, + package_json: &package_json, + lockfile: None, + dependency_groups: [ + DependencyGroup::Default, + DependencyGroup::Dev, + DependencyGroup::Optional, + ], + frozen_lockfile: false, + } + .run() + .await; + + // Make sure the package is installed + assert!(is_symlink_or_junction(project_root.join("node_modules/is-odd")).unwrap()); + assert!(project_root.join("node_modules/.pacquet/is-odd@3.0.1").exists()); + // Make sure it installs direct dependencies + assert!(!project_root.join("node_modules/is-number").exists()); + assert!(project_root.join("node_modules/.pacquet/is-number@6.0.0").exists()); + // Make sure we install dev-dependencies as well + assert!(is_symlink_or_junction( + project_root.join("node_modules/fast-decode-uri-component") + ) + .unwrap()); + assert!(project_root + .join("node_modules/.pacquet/fast-decode-uri-component@1.0.1") + .is_dir()); + + insta::assert_debug_snapshot!(get_all_folders(&project_root)); + + // env::set_current_dir(¤t_directory).unwrap(); + } +} diff --git a/crates/cli/src/commands/snapshots/pacquet_cli__commands__install__tests__should_install_dependencies.snap b/crates/package_manager/src/pacquet_cli__commands__install__tests__should_install_dependencies.snap.tmp similarity index 100% rename from crates/cli/src/commands/snapshots/pacquet_cli__commands__install__tests__should_install_dependencies.snap rename to crates/package_manager/src/pacquet_cli__commands__install__tests__should_install_dependencies.snap.tmp diff --git a/crates/package_manager/src/snapshots/pacquet_package_manager__install__tests__should_install_dependencies.snap b/crates/package_manager/src/snapshots/pacquet_package_manager__install__tests__should_install_dependencies.snap new file mode 100644 index 000000000..e4e005181 --- /dev/null +++ b/crates/package_manager/src/snapshots/pacquet_package_manager__install__tests__should_install_dependencies.snap @@ -0,0 +1,21 @@ +--- +source: crates/package_manager/src/install.rs +assertion_line: 184 +expression: get_all_folders(&project_root) +--- +[ + "node_modules", + "node_modules/.pacquet", + "node_modules/.pacquet/fast-decode-uri-component@1.0.1", + "node_modules/.pacquet/fast-decode-uri-component@1.0.1/node_modules", + "node_modules/.pacquet/fast-decode-uri-component@1.0.1/node_modules/fast-decode-uri-component", + "node_modules/.pacquet/is-number@6.0.0", + "node_modules/.pacquet/is-number@6.0.0/node_modules", + "node_modules/.pacquet/is-number@6.0.0/node_modules/is-number", + "node_modules/.pacquet/is-odd@3.0.1", + "node_modules/.pacquet/is-odd@3.0.1/node_modules", + "node_modules/.pacquet/is-odd@3.0.1/node_modules/is-number", + "node_modules/.pacquet/is-odd@3.0.1/node_modules/is-odd", + "node_modules/fast-decode-uri-component", + "node_modules/is-odd", +] From 4807700fceedab9a1b3720b05310b9896a25d7f2 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 13 Oct 2023 20:14:34 +0700 Subject: [PATCH 084/210] docs: remove useless comment --- crates/package_manager/src/install.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/crates/package_manager/src/install.rs b/crates/package_manager/src/install.rs index c99044430..08c651279 100644 --- a/crates/package_manager/src/install.rs +++ b/crates/package_manager/src/install.rs @@ -131,9 +131,6 @@ mod tests { let modules_dir = project_root.join("node_modules"); // TODO: we shouldn't have to define this let virtual_store_dir = modules_dir.join(".pacquet"); // TODO: we shouldn't have to define this - // let current_directory = env::current_dir().unwrap(); - // env::set_current_dir(dir.path()).unwrap(); - let package_json_path = dir.path().join("package.json"); let mut package_json = PackageJson::create_if_needed(package_json_path.clone()).unwrap(); @@ -182,7 +179,5 @@ mod tests { .is_dir()); insta::assert_debug_snapshot!(get_all_folders(&project_root)); - - // env::set_current_dir(¤t_directory).unwrap(); } } From 7f72108ecd2dd16e0577d63e302b579332ad1923 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 13 Oct 2023 21:31:36 +0700 Subject: [PATCH 085/210] refactor: make add reuse install --- crates/cli/src/commands/add.rs | 117 +++++++++--------------------- crates/cli/src/package_manager.rs | 5 -- 2 files changed, 33 insertions(+), 89 deletions(-) diff --git a/crates/cli/src/commands/add.rs b/crates/cli/src/commands/add.rs index cf80850de..17cc1088a 100644 --- a/crates/cli/src/commands/add.rs +++ b/crates/cli/src/commands/add.rs @@ -1,12 +1,7 @@ -use clap::Parser; -use node_semver::Version; -use std::collections::VecDeque; - use crate::package_manager::{PackageManager, PackageManagerError}; -use futures_util::{future, TryFutureExt}; -use pacquet_diagnostics::miette::WrapErr; +use clap::Parser; use pacquet_package_json::DependencyGroup; -use pacquet_package_manager::InstallPackageFromRegistry; +use pacquet_package_manager::Install; use pacquet_registry::{PackageTag, PackageVersion}; #[derive(Parser, Debug)] @@ -58,91 +53,45 @@ impl PackageManager { /// 5. Symlink all dependencies to node_modules/.pacquet/pkg@version/node_modules /// 6. Update package.json pub async fn add(&mut self, args: &AddCommandArgs) -> Result<(), PackageManagerError> { - let latest_version = InstallPackageFromRegistry { - tarball_cache: &self.tarball_cache, - config: self.config, - http_client: &self.http_client, - name: &args.package, - version_range: "latest", // TODO: add support for specifying tags - node_modules_dir: &self.config.modules_dir, - } - .run::() + let PackageManager { config, package_json, lockfile, http_client, tarball_cache } = self; + + let latest_version = PackageVersion::fetch_from_registry( + &args.package, + PackageTag::Latest, // TODO: add support for specifying tags + http_client, + &config.registry, + ) .await - .map_err(PackageManagerError::InstallPackageFromRegistry)?; - let package_node_modules_path = self - .config - .virtual_store_dir - .join(latest_version.to_virtual_store_name()) - .join("node_modules"); - - let mut queue: VecDeque>> = VecDeque::new(); - let config = &self.config; - let http_client = &self.http_client; - - let direct_dependency_handles = - latest_version.dependencies(self.config.auto_install_peers).map(|(name, version)| { - InstallPackageFromRegistry { - tarball_cache: &self.tarball_cache, - http_client, - config, - node_modules_dir: &package_node_modules_path, - name, - version_range: version, - } - .run::() - .map_err(PackageManagerError::InstallPackageFromRegistry) - }); - - queue.push_front(future::join_all(direct_dependency_handles).await); + .expect("resolve latest tag"); // TODO: properly propagate this error - while let Some(dependencies) = queue.pop_front() { - for dependency in dependencies { - let dependency = - dependency.wrap_err("failed to install one of the dependencies.").unwrap(); - let node_modules_path = self - .config - .virtual_store_dir - .join(dependency.to_virtual_store_name()) - .join("node_modules"); + let version_range = latest_version.serialize(args.save_exact); + let dependency_group = args.dependency_group(); - let handles = dependency.dependencies(self.config.auto_install_peers).map( - |(name, version)| { - InstallPackageFromRegistry { - tarball_cache: &self.tarball_cache, - http_client, - config, - node_modules_dir: &node_modules_path, - name, - version_range: version, - } - .run::() - .map_err(PackageManagerError::InstallPackageFromRegistry) - }, - ); - - queue.push_back(future::join_all(handles).await); - } - } - - self.package_json - .add_dependency( - &args.package, - &latest_version.serialize(args.save_exact), - args.dependency_group(), - ) + package_json + .add_dependency(&args.package, &version_range, dependency_group) .map_err(PackageManagerError::PackageJson)?; + // Using --save-peer will add one or more packages to peerDependencies and // install them as dev dependencies - if args.dependency_group() == DependencyGroup::Peer { - self.package_json - .add_dependency( - &args.package, - &latest_version.serialize(args.save_exact), - DependencyGroup::Dev, - ) + if dependency_group == DependencyGroup::Peer { + package_json + .add_dependency(&args.package, &version_range, DependencyGroup::Dev) .map_err(PackageManagerError::PackageJson)?; } - self.package_json.save().map_err(PackageManagerError::PackageJson)?; + + Install { + tarball_cache, + http_client, + config, + package_json, + lockfile: lockfile.as_ref(), + dependency_groups: [dependency_group], + frozen_lockfile: false, + } + .run() + .await; + + package_json.save().map_err(PackageManagerError::PackageJson)?; Ok(()) } diff --git a/crates/cli/src/package_manager.rs b/crates/cli/src/package_manager.rs index b27d2a3e2..07ccaea4d 100644 --- a/crates/cli/src/package_manager.rs +++ b/crates/cli/src/package_manager.rs @@ -7,7 +7,6 @@ use pacquet_diagnostics::{ use pacquet_lockfile::Lockfile; use pacquet_npmrc::Npmrc; use pacquet_package_json::PackageJson; -use pacquet_package_manager::InstallPackageFromRegistryError; use pacquet_tarball::Cache; use pipe_trait::Pipe; @@ -21,10 +20,6 @@ pub enum PackageManagerError { #[error(transparent)] #[diagnostic(transparent)] LoadLockfileError(pacquet_lockfile::LoadLockfileError), - - #[error(transparent)] - #[diagnostic(transparent)] - InstallPackageFromRegistry(InstallPackageFromRegistryError), } pub struct PackageManager { From 050e2b49682bbf6f1b8fe933ad028be0098a7c2d Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 13 Oct 2023 23:08:21 +0700 Subject: [PATCH 086/210] fix(windows): missing dependencies --- Cargo.lock | 1 + crates/package_manager/Cargo.toml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 2b3818f8c..bc192ae1c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1392,6 +1392,7 @@ dependencies = [ "derive_more", "futures-util", "insta", + "junction", "miette", "node-semver", "pacquet_fs", diff --git a/crates/package_manager/Cargo.toml b/crates/package_manager/Cargo.toml index 3bf3c64d9..36ef4c440 100644 --- a/crates/package_manager/Cargo.toml +++ b/crates/package_manager/Cargo.toml @@ -36,3 +36,6 @@ pretty_assertions = { workspace = true } tempfile = { workspace = true } tokio = { workspace = true } walkdir = { workspace = true } + +[target.'cfg(windows)'.dev-dependencies] +junction = { workspace = true } From ea6207c691c3cc6372effa1e901531f071476853 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 13 Oct 2023 23:21:27 +0700 Subject: [PATCH 087/210] refactor(test): move util functions to a crate --- Cargo.lock | 9 +++++++++ Cargo.toml | 1 + crates/cli/Cargo.toml | 2 ++ crates/cli/src/commands/add.rs | 3 +-- crates/cli/src/lib.rs | 1 - crates/package_manager/Cargo.toml | 2 ++ crates/package_manager/src/install.rs | 26 +------------------------ crates/testing-utils/Cargo.toml | 14 +++++++++++++ crates/{cli => testing-utils}/src/fs.rs | 3 --- crates/testing-utils/src/lib.rs | 1 + 10 files changed, 31 insertions(+), 31 deletions(-) create mode 100644 crates/testing-utils/Cargo.toml rename crates/{cli => testing-utils}/src/fs.rs (96%) create mode 100644 crates/testing-utils/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index bc192ae1c..1e32028a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1276,6 +1276,7 @@ dependencies = [ "pacquet_package_manager", "pacquet_registry", "pacquet_tarball", + "pacquet_testing_utils", "pipe-trait", "pretty_assertions", "rayon", @@ -1401,6 +1402,7 @@ dependencies = [ "pacquet_package_json", "pacquet_registry", "pacquet_tarball", + "pacquet_testing_utils", "pipe-trait", "pretty_assertions", "rayon", @@ -1445,6 +1447,13 @@ dependencies = [ "zune-inflate", ] +[[package]] +name = "pacquet_testing_utils" +version = "0.0.0" +dependencies = [ + "walkdir", +] + [[package]] name = "parking_lot" version = "0.12.1" diff --git a/Cargo.toml b/Cargo.toml index cee68fa71..8cd4ca14b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ pacquet_cli = { path = "crates/cli" } pacquet_fs = { path = "crates/fs" } pacquet_registry = { path = "crates/registry" } pacquet_tarball = { path = "crates/tarball" } +pacquet_testing_utils = { path = "crates/testing-utils" } pacquet_package_json = { path = "crates/package_json" } pacquet_package_manager = { path = "crates/package_manager" } pacquet_lockfile = { path = "crates/lockfile" } diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 1e09125b9..e0b6e9b3a 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -39,6 +39,8 @@ serde_json = { workspace = true } tokio = { workspace = true } [dev-dependencies] +pacquet_testing_utils = { workspace = true } + insta = { workspace = true } pretty_assertions = { workspace = true } tempfile = { workspace = true } diff --git a/crates/cli/src/commands/add.rs b/crates/cli/src/commands/add.rs index 17cc1088a..b2b675ab6 100644 --- a/crates/cli/src/commands/add.rs +++ b/crates/cli/src/commands/add.rs @@ -99,12 +99,11 @@ impl PackageManager { #[cfg(test)] mod tests { - use crate::fs::get_all_folders; use std::{env, fs}; - use crate::fs::get_filenames_in_folder; use pacquet_npmrc::Npmrc; use pacquet_package_json::{DependencyGroup, PackageJson}; + use pacquet_testing_utils::fs::{get_all_folders, get_filenames_in_folder}; use pretty_assertions::assert_eq; use tempfile::tempdir; diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index f58a2d9b4..8ca4298ad 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -1,5 +1,4 @@ mod commands; -mod fs; mod package_manager; use crate::package_manager::PackageManager; diff --git a/crates/package_manager/Cargo.toml b/crates/package_manager/Cargo.toml index 36ef4c440..eea98e56a 100644 --- a/crates/package_manager/Cargo.toml +++ b/crates/package_manager/Cargo.toml @@ -30,6 +30,8 @@ tracing = { workspace = true } miette = { workspace = true } [dev-dependencies] +pacquet_testing_utils = { workspace = true } + node-semver = { workspace = true } insta = { workspace = true } pretty_assertions = { workspace = true } diff --git a/crates/package_manager/src/install.rs b/crates/package_manager/src/install.rs index 08c651279..788662dbb 100644 --- a/crates/package_manager/src/install.rs +++ b/crates/package_manager/src/install.rs @@ -86,6 +86,7 @@ mod tests { use super::*; use pacquet_npmrc::Npmrc; use pacquet_package_json::{DependencyGroup, PackageJson}; + use pacquet_testing_utils::fs::get_all_folders; use std::{env, io}; use tempfile::tempdir; @@ -98,31 +99,6 @@ mod tests { return Ok(path.is_symlink()); } - pub fn get_all_folders(root: &std::path::Path) -> Vec { - let mut files = Vec::new(); - for entry in walkdir::WalkDir::new(root) { - let entry = entry.unwrap(); - let entry_path = entry.path(); - if entry.file_type().is_dir() || entry.file_type().is_symlink() { - // We need this mutation to ensure that both Unix and Windows paths resolves the same. - // TODO: Find a better way to do this? - let simple_path = entry_path - .strip_prefix(root) - .unwrap() - .components() - .map(|c| c.as_os_str().to_str().expect("invalid UTF-8")) - .collect::>() - .join("/"); - - if !simple_path.is_empty() { - files.push(simple_path); - } - } - } - files.sort(); - files - } - #[tokio::test] pub async fn should_install_dependencies() { let dir = tempdir().unwrap(); diff --git a/crates/testing-utils/Cargo.toml b/crates/testing-utils/Cargo.toml new file mode 100644 index 000000000..754a40666 --- /dev/null +++ b/crates/testing-utils/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "pacquet_testing_utils" +version = "0.0.0" +description = "Common utilities to test pacquet code" +publish = false +authors.workspace = true +edition.workspace = true +homepage.workspace = true +keywords.workspace = true +license.workspace = true +repository.workspace = true + +[dependencies] +walkdir = { workspace = true } diff --git a/crates/cli/src/fs.rs b/crates/testing-utils/src/fs.rs similarity index 96% rename from crates/cli/src/fs.rs rename to crates/testing-utils/src/fs.rs index 52b943df0..8b676cd06 100644 --- a/crates/cli/src/fs.rs +++ b/crates/testing-utils/src/fs.rs @@ -1,7 +1,5 @@ -#[cfg(test)] use std::path::Path; -#[cfg(test)] pub fn get_filenames_in_folder(path: &Path) -> Vec { let mut files = std::fs::read_dir(path) .unwrap() @@ -12,7 +10,6 @@ pub fn get_filenames_in_folder(path: &Path) -> Vec { files } -#[cfg(test)] pub fn get_all_folders(root: &std::path::Path) -> Vec { let mut files = Vec::new(); for entry in walkdir::WalkDir::new(root) { diff --git a/crates/testing-utils/src/lib.rs b/crates/testing-utils/src/lib.rs new file mode 100644 index 000000000..d521fbd77 --- /dev/null +++ b/crates/testing-utils/src/lib.rs @@ -0,0 +1 @@ +pub mod fs; From d31beab1d5f8fbcc3569c7b7c890567086b82da6 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 13 Oct 2023 23:23:02 +0700 Subject: [PATCH 088/210] style: remove some empty lines --- crates/cli/src/commands/add.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/cli/src/commands/add.rs b/crates/cli/src/commands/add.rs index b2b675ab6..5eaf30998 100644 --- a/crates/cli/src/commands/add.rs +++ b/crates/cli/src/commands/add.rs @@ -99,16 +99,14 @@ impl PackageManager { #[cfg(test)] mod tests { - use std::{env, fs}; - + use super::*; use pacquet_npmrc::Npmrc; use pacquet_package_json::{DependencyGroup, PackageJson}; use pacquet_testing_utils::fs::{get_all_folders, get_filenames_in_folder}; use pretty_assertions::assert_eq; + use std::{env, fs}; use tempfile::tempdir; - use super::*; - #[tokio::test] pub async fn should_install_all_dependencies() { let dir = tempdir().unwrap(); From 896f30da2a8bde4689ea45419720a75379e36172 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 13 Oct 2023 23:23:32 +0700 Subject: [PATCH 089/210] chore: remove unused file --- ...ests__should_install_dependencies.snap.tmp | 20 ------------------- 1 file changed, 20 deletions(-) delete mode 100644 crates/package_manager/src/pacquet_cli__commands__install__tests__should_install_dependencies.snap.tmp diff --git a/crates/package_manager/src/pacquet_cli__commands__install__tests__should_install_dependencies.snap.tmp b/crates/package_manager/src/pacquet_cli__commands__install__tests__should_install_dependencies.snap.tmp deleted file mode 100644 index 8d0636664..000000000 --- a/crates/package_manager/src/pacquet_cli__commands__install__tests__should_install_dependencies.snap.tmp +++ /dev/null @@ -1,20 +0,0 @@ ---- -source: crates/cli/src/commands/install.rs -expression: get_all_folders(&dir.path().to_path_buf()) ---- -[ - "node_modules", - "node_modules/.pacquet", - "node_modules/.pacquet/fast-decode-uri-component@1.0.1", - "node_modules/.pacquet/fast-decode-uri-component@1.0.1/node_modules", - "node_modules/.pacquet/fast-decode-uri-component@1.0.1/node_modules/fast-decode-uri-component", - "node_modules/.pacquet/is-number@6.0.0", - "node_modules/.pacquet/is-number@6.0.0/node_modules", - "node_modules/.pacquet/is-number@6.0.0/node_modules/is-number", - "node_modules/.pacquet/is-odd@3.0.1", - "node_modules/.pacquet/is-odd@3.0.1/node_modules", - "node_modules/.pacquet/is-odd@3.0.1/node_modules/is-number", - "node_modules/.pacquet/is-odd@3.0.1/node_modules/is-odd", - "node_modules/fast-decode-uri-component", - "node_modules/is-odd", -] From 2e1c00dd8cfcea8dbb15d09f17b366fa779c2e34 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Fri, 13 Oct 2023 23:37:10 +0700 Subject: [PATCH 090/210] refactor(test): move a function to utils --- Cargo.lock | 3 +-- crates/cli/Cargo.toml | 3 --- crates/package_manager/Cargo.toml | 3 --- crates/package_manager/src/install.rs | 17 ++++------------- crates/testing-utils/Cargo.toml | 3 +++ crates/testing-utils/src/fs.rs | 11 ++++++++++- 6 files changed, 18 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1e32028a6..f576aed21 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1264,7 +1264,6 @@ dependencies = [ "clap", "futures-util", "insta", - "junction", "node-semver", "pacquet_cafs", "pacquet_diagnostics", @@ -1393,7 +1392,6 @@ dependencies = [ "derive_more", "futures-util", "insta", - "junction", "miette", "node-semver", "pacquet_fs", @@ -1451,6 +1449,7 @@ dependencies = [ name = "pacquet_testing_utils" version = "0.0.0" dependencies = [ + "junction", "walkdir", ] diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index e0b6e9b3a..583fda692 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -45,6 +45,3 @@ insta = { workspace = true } pretty_assertions = { workspace = true } tempfile = { workspace = true } walkdir = { workspace = true } - -[target.'cfg(windows)'.dev-dependencies] -junction = { workspace = true } diff --git a/crates/package_manager/Cargo.toml b/crates/package_manager/Cargo.toml index eea98e56a..e1afd8a46 100644 --- a/crates/package_manager/Cargo.toml +++ b/crates/package_manager/Cargo.toml @@ -38,6 +38,3 @@ pretty_assertions = { workspace = true } tempfile = { workspace = true } tokio = { workspace = true } walkdir = { workspace = true } - -[target.'cfg(windows)'.dev-dependencies] -junction = { workspace = true } diff --git a/crates/package_manager/src/install.rs b/crates/package_manager/src/install.rs index 788662dbb..5043cf27b 100644 --- a/crates/package_manager/src/install.rs +++ b/crates/package_manager/src/install.rs @@ -86,19 +86,10 @@ mod tests { use super::*; use pacquet_npmrc::Npmrc; use pacquet_package_json::{DependencyGroup, PackageJson}; - use pacquet_testing_utils::fs::get_all_folders; - use std::{env, io}; + use pacquet_testing_utils::fs::{get_all_folders, is_symlink_or_junction}; + use std::env; use tempfile::tempdir; - // Helper function to check if a path is a symlink or junction - fn is_symlink_or_junction(path: std::path::PathBuf) -> io::Result { - #[cfg(windows)] - return junction::exists(&path); - - #[cfg(not(windows))] - return Ok(path.is_symlink()); - } - #[tokio::test] pub async fn should_install_dependencies() { let dir = tempdir().unwrap(); @@ -140,14 +131,14 @@ mod tests { .await; // Make sure the package is installed - assert!(is_symlink_or_junction(project_root.join("node_modules/is-odd")).unwrap()); + assert!(is_symlink_or_junction(&project_root.join("node_modules/is-odd")).unwrap()); assert!(project_root.join("node_modules/.pacquet/is-odd@3.0.1").exists()); // Make sure it installs direct dependencies assert!(!project_root.join("node_modules/is-number").exists()); assert!(project_root.join("node_modules/.pacquet/is-number@6.0.0").exists()); // Make sure we install dev-dependencies as well assert!(is_symlink_or_junction( - project_root.join("node_modules/fast-decode-uri-component") + &project_root.join("node_modules/fast-decode-uri-component") ) .unwrap()); assert!(project_root diff --git a/crates/testing-utils/Cargo.toml b/crates/testing-utils/Cargo.toml index 754a40666..e443a60a4 100644 --- a/crates/testing-utils/Cargo.toml +++ b/crates/testing-utils/Cargo.toml @@ -12,3 +12,6 @@ repository.workspace = true [dependencies] walkdir = { workspace = true } + +[target.'cfg(windows)'.dependencies] +junction = { workspace = true } diff --git a/crates/testing-utils/src/fs.rs b/crates/testing-utils/src/fs.rs index 8b676cd06..64d571f02 100644 --- a/crates/testing-utils/src/fs.rs +++ b/crates/testing-utils/src/fs.rs @@ -1,4 +1,4 @@ -use std::path::Path; +use std::{io, path::Path}; pub fn get_filenames_in_folder(path: &Path) -> Vec { let mut files = std::fs::read_dir(path) @@ -34,3 +34,12 @@ pub fn get_all_folders(root: &std::path::Path) -> Vec { files.sort(); files } + +// Helper function to check if a path is a symlink or junction +pub fn is_symlink_or_junction(path: &Path) -> io::Result { + #[cfg(windows)] + return junction::exists(&path); + + #[cfg(not(windows))] + return Ok(path.is_symlink()); +} From 8fcc5a991e1027a3c58603409d4a2b298624e931 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 01:02:25 +0700 Subject: [PATCH 091/210] docs: move the brief overview --- crates/cli/src/commands/add.rs | 7 ------- crates/package_manager/src/install_without_lockfile.rs | 8 ++++++++ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/crates/cli/src/commands/add.rs b/crates/cli/src/commands/add.rs index 5eaf30998..20d57b4eb 100644 --- a/crates/cli/src/commands/add.rs +++ b/crates/cli/src/commands/add.rs @@ -45,13 +45,6 @@ impl AddCommandArgs { } impl PackageManager { - /// Here is a brief overview of what this package does. - /// 1. Get a dependency - /// 2. Save the dependency to node_modules/.pacquet/pkg@version/node_modules/pkg - /// 3. Create a symlink to node_modules/pkg - /// 4. Download all dependencies to node_modules/.pacquet - /// 5. Symlink all dependencies to node_modules/.pacquet/pkg@version/node_modules - /// 6. Update package.json pub async fn add(&mut self, args: &AddCommandArgs) -> Result<(), PackageManagerError> { let PackageManager { config, package_json, lockfile, http_client, tarball_cache } = self; diff --git a/crates/package_manager/src/install_without_lockfile.rs b/crates/package_manager/src/install_without_lockfile.rs index aae24daaa..806c96e8d 100644 --- a/crates/package_manager/src/install_without_lockfile.rs +++ b/crates/package_manager/src/install_without_lockfile.rs @@ -10,6 +10,14 @@ use pipe_trait::Pipe; use reqwest::Client; /// This subroutine install packages from a `package.json` without reading or writing a lockfile. +/// +/// **Brief overview for each package:** +/// * Fetch a tarball of the package. +/// * Extract the tarball into the store directory. +/// * Import (by reflink, hardlink, or copy) the files from the store dir to `node_modules/.pacquet/{name}@{version}/node_modules/{name}/`. +/// * Create dependency symbolic links in `node_modules/.pacquet/{name}@{version}/node_modules/`. +/// * Create a symbolic link at `node_modules/{name}`. +/// * Repeat the process for the dependencies of the package. #[must_use] pub struct InstallWithoutLockfile<'a, DependencyGroupList> { /// Shared cache that store downloaded tarballs. From 27305774927e3f6452287b4cce268ad9ac678c78 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 01:09:36 +0700 Subject: [PATCH 092/210] docs: brief overview for frozen lockfile algorithm --- crates/package_manager/src/install_frozen_lockfile.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/package_manager/src/install_frozen_lockfile.rs b/crates/package_manager/src/install_frozen_lockfile.rs index bc909c18b..5c710b23a 100644 --- a/crates/package_manager/src/install_frozen_lockfile.rs +++ b/crates/package_manager/src/install_frozen_lockfile.rs @@ -7,6 +7,14 @@ use reqwest::Client; use std::collections::HashMap; /// This subroutine installs dependencies from a frozen lockfile. +/// +/// **Brief overview:** +/// * Iterate over each package in [`Self::packages`]. +/// * Fetch a tarball of each package. +/// * Extract each tarball into the store directory. +/// * Import (by reflink, hardlink, or copy) the files from the store dir to each `node_modules/.pacquet/{name}@{version}/node_modules/{name}/`. +/// * Create dependency symbolic links in each `node_modules/.pacquet/{name}@{version}/node_modules/`. +/// * Create a symbolic link at each `node_modules/{name}`. #[must_use] pub struct InstallFrozenLockfile<'a, DependencyGroupList> where From e8be328335373f198af67aeb68e54bcfd06d5107 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 01:24:24 +0700 Subject: [PATCH 093/210] style: merge imports --- crates/cli/src/lib.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index 8ca4298ad..e28ee6046 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -1,11 +1,9 @@ mod commands; mod package_manager; -use crate::package_manager::PackageManager; - -use crate::commands::store::StoreSubcommands; -use crate::commands::{Cli, Subcommands}; use clap::Parser; +use commands::{store::StoreSubcommands, Cli, Subcommands}; +use package_manager::PackageManager; use pacquet_diagnostics::{ enable_tracing_by_env, miette::{set_panic_hook, IntoDiagnostic, Result, WrapErr}, From c42730d9091cb0f5b448a8d789a08b1549fc6764 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 01:31:59 +0700 Subject: [PATCH 094/210] refactor: rename cli types --- crates/cli/src/commands/add.rs | 16 +++++------ crates/cli/src/commands/install.rs | 6 ++-- crates/cli/src/commands/mod.rs | 22 +++++++-------- crates/cli/src/commands/run.rs | 2 +- crates/cli/src/commands/store.rs | 2 +- crates/cli/src/lib.rs | 45 +++++++++++++++++------------- 6 files changed, 48 insertions(+), 45 deletions(-) diff --git a/crates/cli/src/commands/add.rs b/crates/cli/src/commands/add.rs index 20d57b4eb..8ea580890 100644 --- a/crates/cli/src/commands/add.rs +++ b/crates/cli/src/commands/add.rs @@ -5,7 +5,7 @@ use pacquet_package_manager::Install; use pacquet_registry::{PackageTag, PackageVersion}; #[derive(Parser, Debug)] -pub struct AddCommandArgs { +pub struct AddArgs { /// Name of the package pub package: String, /// Install the specified packages as regular dependencies. @@ -30,7 +30,7 @@ pub struct AddCommandArgs { pub virtual_store_dir: String, } -impl AddCommandArgs { +impl AddArgs { pub fn dependency_group(&self) -> DependencyGroup { if self.save_dev { DependencyGroup::Dev @@ -45,7 +45,7 @@ impl AddCommandArgs { } impl PackageManager { - pub async fn add(&mut self, args: &AddCommandArgs) -> Result<(), PackageManagerError> { + pub async fn add(&mut self, args: &AddArgs) -> Result<(), PackageManagerError> { let PackageManager { config, package_json, lockfile, http_client, tarball_cache } = self; let latest_version = PackageVersion::fetch_from_registry( @@ -112,7 +112,7 @@ mod tests { // It should create a package_json if not exist assert!(package_json.exists()); - let args = AddCommandArgs { + let args = AddArgs { package: "is-even".to_string(), save_prod: false, save_dev: false, @@ -150,7 +150,7 @@ mod tests { let package_json = dir.path().join("package.json"); let mut manager = PackageManager::new(&package_json, Npmrc::current().leak()).unwrap(); - let args = AddCommandArgs { + let args = AddArgs { package: "is-odd".to_string(), save_prod: false, save_dev: false, @@ -181,7 +181,7 @@ mod tests { let package_json = dir.path().join("package.json"); let mut manager = PackageManager::new(&package_json, Npmrc::current().leak()).unwrap(); - let args = AddCommandArgs { + let args = AddArgs { package: "is-odd".to_string(), save_prod: false, save_dev: false, @@ -205,7 +205,7 @@ mod tests { let package_json = dir.path().join("package.json"); let mut manager = PackageManager::new(&package_json, Npmrc::current().leak()).unwrap(); - let args = AddCommandArgs { + let args = AddArgs { package: "is-odd".to_string(), save_prod: false, save_dev: true, @@ -229,7 +229,7 @@ mod tests { let package_json = dir.path().join("package.json"); let mut manager = PackageManager::new(&package_json, Npmrc::current().leak()).unwrap(); - let args = AddCommandArgs { + let args = AddArgs { package: "is-odd".to_string(), save_prod: false, save_dev: false, diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/commands/install.rs index f2f93e96e..41aad1e78 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/commands/install.rs @@ -37,7 +37,7 @@ impl CliDependencyOptions { } #[derive(Parser, Debug)] -pub struct InstallCommandArgs { +pub struct InstallArgs { /// --prod, --dev, and --no-optional #[clap(flatten)] pub dependency_options: CliDependencyOptions, @@ -49,9 +49,9 @@ pub struct InstallCommandArgs { impl PackageManager { /// Jobs of the `install` command. - pub async fn install(&self, args: &InstallCommandArgs) -> Result<(), PackageManagerError> { + pub async fn install(&self, args: &InstallArgs) -> Result<(), PackageManagerError> { let PackageManager { config, http_client, tarball_cache, lockfile, package_json } = self; - let InstallCommandArgs { dependency_options, frozen_lockfile } = args; + let InstallArgs { dependency_options, frozen_lockfile } = args; Install { tarball_cache, diff --git a/crates/cli/src/commands/mod.rs b/crates/cli/src/commands/mod.rs index b0d2e8879..6788beb50 100644 --- a/crates/cli/src/commands/mod.rs +++ b/crates/cli/src/commands/mod.rs @@ -5,9 +5,7 @@ pub mod store; use std::{env, ffi::OsString, path::PathBuf}; -use crate::commands::{ - add::AddCommandArgs, install::InstallCommandArgs, run::RunCommandArgs, store::StoreSubcommands, -}; +use crate::commands::{add::AddArgs, install::InstallArgs, run::RunArgs, store::StoreCommand}; use clap::{Parser, Subcommand}; fn default_current_dir() -> OsString { @@ -20,30 +18,30 @@ fn default_current_dir() -> OsString { #[command(bin_name = "pacquet")] #[command(version = "0.2.1")] #[command(about = "Experimental package manager for node.js")] -pub struct Cli { +pub struct CliArgs { #[command(subcommand)] - pub subcommand: Subcommands, + pub command: CliCommand, - /// Run as if pacquet was started in instead of the current working directory. + /// Set working directory. #[arg(short = 'C', long = "dir", default_value = default_current_dir())] - pub current_dir: PathBuf, + pub dir: PathBuf, } #[derive(Subcommand, Debug)] -pub enum Subcommands { +pub enum CliCommand { /// Initialize a package.json Init, /// Add a package - Add(AddCommandArgs), + Add(AddArgs), /// Install packages - Install(InstallCommandArgs), + Install(InstallArgs), /// Runs a package's "test" script, if one was provided. Test, /// Runs a defined package script. - Run(RunCommandArgs), + Run(RunArgs), /// Runs an arbitrary command specified in the package's start property of its scripts object. Start, /// Managing the package store. #[clap(subcommand)] - Store(StoreSubcommands), + Store(StoreCommand), } diff --git a/crates/cli/src/commands/run.rs b/crates/cli/src/commands/run.rs index 8cb7d6f3b..0cee83a1e 100644 --- a/crates/cli/src/commands/run.rs +++ b/crates/cli/src/commands/run.rs @@ -1,7 +1,7 @@ use clap::Parser; #[derive(Parser, Debug)] -pub struct RunCommandArgs { +pub struct RunArgs { /// A pre-defined package script. pub command: String, diff --git a/crates/cli/src/commands/store.rs b/crates/cli/src/commands/store.rs index 334339313..128baf077 100644 --- a/crates/cli/src/commands/store.rs +++ b/crates/cli/src/commands/store.rs @@ -1,7 +1,7 @@ use clap::Subcommand; #[derive(Subcommand, Debug)] -pub enum StoreSubcommands { +pub enum StoreCommand { /// Checks for modified packages in the store. Store, /// Functionally equivalent to pnpm add, except this adds new packages to the store directly diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index e28ee6046..2dc867dae 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -2,7 +2,7 @@ mod commands; mod package_manager; use clap::Parser; -use commands::{store::StoreSubcommands, Cli, Subcommands}; +use commands::{store::StoreCommand, CliArgs, CliCommand}; use package_manager::PackageManager; use pacquet_diagnostics::{ enable_tracing_by_env, @@ -15,27 +15,27 @@ use pacquet_package_json::PackageJson; pub async fn run_cli() -> Result<()> { enable_tracing_by_env(); set_panic_hook(); - let cli = Cli::parse(); + let cli = CliArgs::parse(); let config = Npmrc::current().leak(); run_commands(cli, config).await } -async fn run_commands(cli: Cli, config: &'static Npmrc) -> Result<()> { - let package_json_path = cli.current_dir.join("package.json"); +async fn run_commands(cli: CliArgs, config: &'static Npmrc) -> Result<()> { + let package_json_path = cli.dir.join("package.json"); - match &cli.subcommand { - Subcommands::Init => { + match &cli.command { + CliCommand::Init => { // init command throws an error if package.json file exist. PackageJson::init(&package_json_path).wrap_err("initialize package.json")?; } - Subcommands::Add(args) => { + CliCommand::Add(args) => { let mut package_manager = PackageManager::new(&package_json_path, config) .wrap_err("initializing the package manager")?; // TODO if a package already exists in another dependency group, we don't remove // the existing entry. package_manager.add(args).await.wrap_err("adding a new package")?; } - Subcommands::Install(args) => { + CliCommand::Install(args) => { let package_manager = PackageManager::new(&package_json_path, config) .wrap_err("initializing the package manager")?; package_manager @@ -44,14 +44,14 @@ async fn run_commands(cli: Cli, config: &'static Npmrc) -> Result<()> { .into_diagnostic() .wrap_err("installing dependencies")?; } - Subcommands::Test => { + CliCommand::Test => { let package_json = PackageJson::from_path(package_json_path) .wrap_err("getting the package.json in current directory")?; if let Some(script) = package_json.script("test", false)? { execute_shell(script).wrap_err(format!("executing command: \"{0}\"", script))?; } } - Subcommands::Run(args) => { + CliCommand::Run(args) => { let package_json = PackageJson::from_path(package_json_path) .wrap_err("getting the package.json in current directory")?; if let Some(script) = package_json.script(&args.command, args.if_present)? { @@ -63,7 +63,7 @@ async fn run_commands(cli: Cli, config: &'static Npmrc) -> Result<()> { execute_shell(command.trim())?; } } - Subcommands::Start => { + CliCommand::Start => { // Runs an arbitrary command specified in the package's start property of its scripts // object. If no start property is specified on the scripts object, it will attempt to // run node server.js as a default, failing if neither are present. @@ -77,17 +77,17 @@ async fn run_commands(cli: Cli, config: &'static Npmrc) -> Result<()> { }; execute_shell(command).wrap_err(format!("executing command: \"{0}\"", command))?; } - Subcommands::Store(subcommand) => match subcommand { - StoreSubcommands::Store => { + CliCommand::Store(command) => match command { + StoreCommand::Store => { panic!("Not implemented") } - StoreSubcommands::Add => { + StoreCommand::Add => { panic!("Not implemented") } - StoreSubcommands::Prune => { + StoreCommand::Prune => { pacquet_cafs::prune_sync(&config.store_dir).wrap_err("pruning store")?; } - StoreSubcommands::Path => { + StoreCommand::Path => { println!("{}", config.store_dir.display()); } }, @@ -107,7 +107,7 @@ mod tests { #[tokio::test] async fn init_command_should_create_package_json() { let parent_folder = tempdir().unwrap(); - let cli = Cli::parse_from(["", "-C", parent_folder.path().to_str().unwrap(), "init"]); + let cli = CliArgs::parse_from(["", "-C", parent_folder.path().to_str().unwrap(), "init"]); run_commands(cli, Npmrc::current().leak()).await.unwrap(); assert!(parent_folder.path().join("package.json").exists()); } @@ -118,15 +118,20 @@ mod tests { let mut file = fs::File::create(parent_folder.path().join("package.json")).unwrap(); file.write_all("{}".as_bytes()).unwrap(); assert!(parent_folder.path().join("package.json").exists()); - let cli = Cli::parse_from(["", "-C", parent_folder.path().to_str().unwrap(), "init"]); + let cli = CliArgs::parse_from(["", "-C", parent_folder.path().to_str().unwrap(), "init"]); run_commands(cli, Npmrc::current().leak()).await.expect_err("should have thrown"); } #[tokio::test] async fn should_get_store_path() { let parent_folder = tempdir().unwrap(); - let cli = - Cli::parse_from(["", "-C", parent_folder.path().to_str().unwrap(), "store", "path"]); + let cli = CliArgs::parse_from([ + "", + "-C", + parent_folder.path().to_str().unwrap(), + "store", + "path", + ]); run_commands(cli, Npmrc::current().leak()).await.unwrap(); } } From 764c744d1be633c5370dd6cb2f9bfa310ed89165 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 01:33:30 +0700 Subject: [PATCH 095/210] style: fix imports --- crates/cli/src/commands/mod.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/cli/src/commands/mod.rs b/crates/cli/src/commands/mod.rs index 6788beb50..8b5a294ad 100644 --- a/crates/cli/src/commands/mod.rs +++ b/crates/cli/src/commands/mod.rs @@ -3,10 +3,12 @@ pub mod install; pub mod run; pub mod store; -use std::{env, ffi::OsString, path::PathBuf}; - -use crate::commands::{add::AddArgs, install::InstallArgs, run::RunArgs, store::StoreCommand}; +use add::AddArgs; use clap::{Parser, Subcommand}; +use install::InstallArgs; +use run::RunArgs; +use std::{env, ffi::OsString, path::PathBuf}; +use store::StoreCommand; fn default_current_dir() -> OsString { env::current_dir().expect("failed to get current directory").into_os_string() From 2be4d72eb01e553e43bf2c98e0c768e7ea571057 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 01:37:08 +0700 Subject: [PATCH 096/210] refactor: rename --- crates/cli/src/bin/main.rs | 2 +- crates/cli/src/lib.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/cli/src/bin/main.rs b/crates/cli/src/bin/main.rs index 47413dc36..60210e146 100644 --- a/crates/cli/src/bin/main.rs +++ b/crates/cli/src/bin/main.rs @@ -2,5 +2,5 @@ use pacquet_diagnostics::Result; #[tokio::main(flavor = "multi_thread")] pub async fn main() -> Result<()> { - pacquet_cli::run_cli().await + pacquet_cli::main().await } diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index 2dc867dae..83685aa54 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -12,15 +12,15 @@ use pacquet_executor::execute_shell; use pacquet_npmrc::Npmrc; use pacquet_package_json::PackageJson; -pub async fn run_cli() -> Result<()> { +pub async fn main() -> Result<()> { enable_tracing_by_env(); set_panic_hook(); let cli = CliArgs::parse(); let config = Npmrc::current().leak(); - run_commands(cli, config).await + run(cli, config).await } -async fn run_commands(cli: CliArgs, config: &'static Npmrc) -> Result<()> { +async fn run(cli: CliArgs, config: &'static Npmrc) -> Result<()> { let package_json_path = cli.dir.join("package.json"); match &cli.command { @@ -108,7 +108,7 @@ mod tests { async fn init_command_should_create_package_json() { let parent_folder = tempdir().unwrap(); let cli = CliArgs::parse_from(["", "-C", parent_folder.path().to_str().unwrap(), "init"]); - run_commands(cli, Npmrc::current().leak()).await.unwrap(); + run(cli, Npmrc::current().leak()).await.unwrap(); assert!(parent_folder.path().join("package.json").exists()); } @@ -119,7 +119,7 @@ mod tests { file.write_all("{}".as_bytes()).unwrap(); assert!(parent_folder.path().join("package.json").exists()); let cli = CliArgs::parse_from(["", "-C", parent_folder.path().to_str().unwrap(), "init"]); - run_commands(cli, Npmrc::current().leak()).await.expect_err("should have thrown"); + run(cli, Npmrc::current().leak()).await.expect_err("should have thrown"); } #[tokio::test] @@ -132,6 +132,6 @@ mod tests { "store", "path", ]); - run_commands(cli, Npmrc::current().leak()).await.unwrap(); + run(cli, Npmrc::current().leak()).await.unwrap(); } } From e5a8cef94ddd5131aa07ec825b905261f82b9074 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 01:39:33 +0700 Subject: [PATCH 097/210] refactor: rename files --- crates/cli/src/{commands => cli_command}/add.rs | 0 crates/cli/src/{commands => cli_command}/install.rs | 2 +- crates/cli/src/{commands => cli_command}/mod.rs | 0 crates/cli/src/{commands => cli_command}/run.rs | 0 ...ommand__add__tests__should_install_all_dependencies.snap} | 5 +++-- ...__cli_command__add__tests__should_symlink_correctly.snap} | 5 +++-- crates/cli/src/{commands => cli_command}/store.rs | 0 crates/cli/src/lib.rs | 4 ++-- 8 files changed, 9 insertions(+), 7 deletions(-) rename crates/cli/src/{commands => cli_command}/add.rs (100%) rename crates/cli/src/{commands => cli_command}/install.rs (98%) rename crates/cli/src/{commands => cli_command}/mod.rs (100%) rename crates/cli/src/{commands => cli_command}/run.rs (100%) rename crates/cli/src/{commands/snapshots/pacquet_cli__commands__add__tests__should_install_all_dependencies.snap => cli_command/snapshots/pacquet_cli__cli_command__add__tests__should_install_all_dependencies.snap} (92%) rename crates/cli/src/{commands/snapshots/pacquet_cli__commands__add__tests__should_symlink_correctly.snap => cli_command/snapshots/pacquet_cli__cli_command__add__tests__should_symlink_correctly.snap} (82%) rename crates/cli/src/{commands => cli_command}/store.rs (100%) diff --git a/crates/cli/src/commands/add.rs b/crates/cli/src/cli_command/add.rs similarity index 100% rename from crates/cli/src/commands/add.rs rename to crates/cli/src/cli_command/add.rs diff --git a/crates/cli/src/commands/install.rs b/crates/cli/src/cli_command/install.rs similarity index 98% rename from crates/cli/src/commands/install.rs rename to crates/cli/src/cli_command/install.rs index 41aad1e78..7ae71e35a 100644 --- a/crates/cli/src/commands/install.rs +++ b/crates/cli/src/cli_command/install.rs @@ -71,7 +71,7 @@ impl PackageManager { #[cfg(test)] mod tests { - use crate::commands::install::CliDependencyOptions; + use crate::cli_command::install::CliDependencyOptions; use pacquet_package_json::DependencyGroup; use pretty_assertions::assert_eq; diff --git a/crates/cli/src/commands/mod.rs b/crates/cli/src/cli_command/mod.rs similarity index 100% rename from crates/cli/src/commands/mod.rs rename to crates/cli/src/cli_command/mod.rs diff --git a/crates/cli/src/commands/run.rs b/crates/cli/src/cli_command/run.rs similarity index 100% rename from crates/cli/src/commands/run.rs rename to crates/cli/src/cli_command/run.rs diff --git a/crates/cli/src/commands/snapshots/pacquet_cli__commands__add__tests__should_install_all_dependencies.snap b/crates/cli/src/cli_command/snapshots/pacquet_cli__cli_command__add__tests__should_install_all_dependencies.snap similarity index 92% rename from crates/cli/src/commands/snapshots/pacquet_cli__commands__add__tests__should_install_all_dependencies.snap rename to crates/cli/src/cli_command/snapshots/pacquet_cli__cli_command__add__tests__should_install_all_dependencies.snap index 7ee81ce5b..5220135c3 100644 --- a/crates/cli/src/commands/snapshots/pacquet_cli__commands__add__tests__should_install_all_dependencies.snap +++ b/crates/cli/src/cli_command/snapshots/pacquet_cli__cli_command__add__tests__should_install_all_dependencies.snap @@ -1,6 +1,7 @@ --- -source: crates/cli/src/commands/add.rs -expression: get_all_folders(&dir.path().to_path_buf()) +source: crates/cli/src/cli_command/add.rs +assertion_line: 126 +expression: get_all_folders(dir.path()) --- [ "node_modules", diff --git a/crates/cli/src/commands/snapshots/pacquet_cli__commands__add__tests__should_symlink_correctly.snap b/crates/cli/src/cli_command/snapshots/pacquet_cli__cli_command__add__tests__should_symlink_correctly.snap similarity index 82% rename from crates/cli/src/commands/snapshots/pacquet_cli__commands__add__tests__should_symlink_correctly.snap rename to crates/cli/src/cli_command/snapshots/pacquet_cli__cli_command__add__tests__should_symlink_correctly.snap index a18831c72..3709a5a7e 100644 --- a/crates/cli/src/commands/snapshots/pacquet_cli__commands__add__tests__should_symlink_correctly.snap +++ b/crates/cli/src/cli_command/snapshots/pacquet_cli__cli_command__add__tests__should_symlink_correctly.snap @@ -1,6 +1,7 @@ --- -source: crates/cli/src/commands/add.rs -expression: get_all_folders(&dir.path().to_path_buf()) +source: crates/cli/src/cli_command/add.rs +assertion_line: 164 +expression: get_all_folders(dir.path()) --- [ "node_modules", diff --git a/crates/cli/src/commands/store.rs b/crates/cli/src/cli_command/store.rs similarity index 100% rename from crates/cli/src/commands/store.rs rename to crates/cli/src/cli_command/store.rs diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index 83685aa54..99e106ff8 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -1,8 +1,8 @@ -mod commands; +mod cli_command; mod package_manager; use clap::Parser; -use commands::{store::StoreCommand, CliArgs, CliCommand}; +use cli_command::{store::StoreCommand, CliArgs, CliCommand}; use package_manager::PackageManager; use pacquet_diagnostics::{ enable_tracing_by_env, From 41784839f333d69acb6a8f9e999ac35371dbac95 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 01:40:36 +0700 Subject: [PATCH 098/210] style: merge imports --- crates/cli/src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index 99e106ff8..e60f51f7e 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -98,12 +98,10 @@ async fn run(cli: CliArgs, config: &'static Npmrc) -> Result<()> { #[cfg(test)] mod tests { + use super::*; use std::{fs, io::Write}; - use tempfile::tempdir; - use super::*; - #[tokio::test] async fn init_command_should_create_package_json() { let parent_folder = tempdir().unwrap(); From 9a88dd3ee162028e70277098791ce1ac99e3c3d6 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 01:42:20 +0700 Subject: [PATCH 099/210] refactor: rename --- crates/cli/src/cli_command/install.rs | 33 +++++++++++++++------------ 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/crates/cli/src/cli_command/install.rs b/crates/cli/src/cli_command/install.rs index 7ae71e35a..0727e9583 100644 --- a/crates/cli/src/cli_command/install.rs +++ b/crates/cli/src/cli_command/install.rs @@ -4,7 +4,7 @@ use pacquet_package_json::DependencyGroup; use pacquet_package_manager::Install; #[derive(Debug, Parser)] -pub struct CliDependencyOptions { +pub struct CliInstallDependencyOptions { /// pacquet will not install any package listed in devDependencies and will remove those insofar /// they were already installed, if the NODE_ENV environment variable is set to production. /// Use this flag to instruct pacquet to ignore NODE_ENV and take its production status from this @@ -20,11 +20,11 @@ pub struct CliDependencyOptions { pub no_optional: bool, } -impl CliDependencyOptions { +impl CliInstallDependencyOptions { /// Convert the command arguments to an iterator of [`DependencyGroup`] /// which filters the types of dependencies to install. fn dependency_groups(&self) -> impl Iterator { - let &CliDependencyOptions { prod, dev, no_optional } = self; + let &CliInstallDependencyOptions { prod, dev, no_optional } = self; let has_both = prod == dev; let has_prod = has_both || prod; let has_dev = has_both || dev; @@ -40,7 +40,7 @@ impl CliDependencyOptions { pub struct InstallArgs { /// --prod, --dev, and --no-optional #[clap(flatten)] - pub dependency_options: CliDependencyOptions, + pub dependency_options: CliInstallDependencyOptions, /// Don't generate a lockfile and fail if the lockfile is outdated. #[clap(long)] @@ -71,60 +71,65 @@ impl PackageManager { #[cfg(test)] mod tests { - use crate::cli_command::install::CliDependencyOptions; + use crate::cli_command::install::CliInstallDependencyOptions; use pacquet_package_json::DependencyGroup; use pretty_assertions::assert_eq; #[test] fn install_args_to_dependency_groups() { use DependencyGroup::{Default, Dev, Optional}; - let create_list = |opts: CliDependencyOptions| opts.dependency_groups().collect::>(); + let create_list = + |opts: CliInstallDependencyOptions| opts.dependency_groups().collect::>(); // no flags -> prod + dev + optional assert_eq!( - create_list(CliDependencyOptions { prod: false, dev: false, no_optional: false }), + create_list(CliInstallDependencyOptions { + prod: false, + dev: false, + no_optional: false + }), [Default, Dev, Optional], ); // --prod -> prod + optional assert_eq!( - create_list(CliDependencyOptions { prod: true, dev: false, no_optional: false }), + create_list(CliInstallDependencyOptions { prod: true, dev: false, no_optional: false }), [Default, Optional], ); // --dev -> dev + optional assert_eq!( - create_list(CliDependencyOptions { prod: false, dev: true, no_optional: false }), + create_list(CliInstallDependencyOptions { prod: false, dev: true, no_optional: false }), [Dev, Optional], ); // --no-optional -> prod + dev assert_eq!( - create_list(CliDependencyOptions { prod: false, dev: false, no_optional: true }), + create_list(CliInstallDependencyOptions { prod: false, dev: false, no_optional: true }), [Default, Dev], ); // --prod --no-optional -> prod assert_eq!( - create_list(CliDependencyOptions { prod: true, dev: false, no_optional: true }), + create_list(CliInstallDependencyOptions { prod: true, dev: false, no_optional: true }), [Default], ); // --dev --no-optional -> dev assert_eq!( - create_list(CliDependencyOptions { prod: false, dev: true, no_optional: true }), + create_list(CliInstallDependencyOptions { prod: false, dev: true, no_optional: true }), [Dev], ); // --prod --dev -> prod + dev + optional assert_eq!( - create_list(CliDependencyOptions { prod: true, dev: true, no_optional: false }), + create_list(CliInstallDependencyOptions { prod: true, dev: true, no_optional: false }), [Default, Dev, Optional], ); // --prod --dev --no-optional -> prod + dev assert_eq!( - create_list(CliDependencyOptions { prod: true, dev: true, no_optional: true }), + create_list(CliInstallDependencyOptions { prod: true, dev: true, no_optional: true }), [Default, Dev], ); } From 75a7a850894b0356d3744e3294f5bfede7d11b63 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 01:42:44 +0700 Subject: [PATCH 100/210] style: shorten import line --- crates/cli/src/cli_command/install.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli/src/cli_command/install.rs b/crates/cli/src/cli_command/install.rs index 0727e9583..ce36fef7f 100644 --- a/crates/cli/src/cli_command/install.rs +++ b/crates/cli/src/cli_command/install.rs @@ -71,7 +71,7 @@ impl PackageManager { #[cfg(test)] mod tests { - use crate::cli_command::install::CliInstallDependencyOptions; + use super::*; use pacquet_package_json::DependencyGroup; use pretty_assertions::assert_eq; From 05a7cab4fbb9ef37fe558a017e5d877333e9e79d Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 12:03:38 +0700 Subject: [PATCH 101/210] refactor: rename --- crates/cli/src/cli_command/install.rs | 30 ++++++++++++--------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/crates/cli/src/cli_command/install.rs b/crates/cli/src/cli_command/install.rs index ce36fef7f..bb8010fa6 100644 --- a/crates/cli/src/cli_command/install.rs +++ b/crates/cli/src/cli_command/install.rs @@ -4,7 +4,7 @@ use pacquet_package_json::DependencyGroup; use pacquet_package_manager::Install; #[derive(Debug, Parser)] -pub struct CliInstallDependencyOptions { +pub struct InstallDependencyOptions { /// pacquet will not install any package listed in devDependencies and will remove those insofar /// they were already installed, if the NODE_ENV environment variable is set to production. /// Use this flag to instruct pacquet to ignore NODE_ENV and take its production status from this @@ -20,11 +20,11 @@ pub struct CliInstallDependencyOptions { pub no_optional: bool, } -impl CliInstallDependencyOptions { +impl InstallDependencyOptions { /// Convert the command arguments to an iterator of [`DependencyGroup`] /// which filters the types of dependencies to install. fn dependency_groups(&self) -> impl Iterator { - let &CliInstallDependencyOptions { prod, dev, no_optional } = self; + let &InstallDependencyOptions { prod, dev, no_optional } = self; let has_both = prod == dev; let has_prod = has_both || prod; let has_dev = has_both || dev; @@ -40,7 +40,7 @@ impl CliInstallDependencyOptions { pub struct InstallArgs { /// --prod, --dev, and --no-optional #[clap(flatten)] - pub dependency_options: CliInstallDependencyOptions, + pub dependency_options: InstallDependencyOptions, /// Don't generate a lockfile and fail if the lockfile is outdated. #[clap(long)] @@ -79,57 +79,53 @@ mod tests { fn install_args_to_dependency_groups() { use DependencyGroup::{Default, Dev, Optional}; let create_list = - |opts: CliInstallDependencyOptions| opts.dependency_groups().collect::>(); + |opts: InstallDependencyOptions| opts.dependency_groups().collect::>(); // no flags -> prod + dev + optional assert_eq!( - create_list(CliInstallDependencyOptions { - prod: false, - dev: false, - no_optional: false - }), + create_list(InstallDependencyOptions { prod: false, dev: false, no_optional: false }), [Default, Dev, Optional], ); // --prod -> prod + optional assert_eq!( - create_list(CliInstallDependencyOptions { prod: true, dev: false, no_optional: false }), + create_list(InstallDependencyOptions { prod: true, dev: false, no_optional: false }), [Default, Optional], ); // --dev -> dev + optional assert_eq!( - create_list(CliInstallDependencyOptions { prod: false, dev: true, no_optional: false }), + create_list(InstallDependencyOptions { prod: false, dev: true, no_optional: false }), [Dev, Optional], ); // --no-optional -> prod + dev assert_eq!( - create_list(CliInstallDependencyOptions { prod: false, dev: false, no_optional: true }), + create_list(InstallDependencyOptions { prod: false, dev: false, no_optional: true }), [Default, Dev], ); // --prod --no-optional -> prod assert_eq!( - create_list(CliInstallDependencyOptions { prod: true, dev: false, no_optional: true }), + create_list(InstallDependencyOptions { prod: true, dev: false, no_optional: true }), [Default], ); // --dev --no-optional -> dev assert_eq!( - create_list(CliInstallDependencyOptions { prod: false, dev: true, no_optional: true }), + create_list(InstallDependencyOptions { prod: false, dev: true, no_optional: true }), [Dev], ); // --prod --dev -> prod + dev + optional assert_eq!( - create_list(CliInstallDependencyOptions { prod: true, dev: true, no_optional: false }), + create_list(InstallDependencyOptions { prod: true, dev: true, no_optional: false }), [Default, Dev, Optional], ); // --prod --dev --no-optional -> prod + dev assert_eq!( - create_list(CliInstallDependencyOptions { prod: true, dev: true, no_optional: true }), + create_list(InstallDependencyOptions { prod: true, dev: true, no_optional: true }), [Default, Dev], ); } From b498a0c66f9709cacef6718de65eaa8482b6e8ef Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 12:23:49 +0700 Subject: [PATCH 102/210] refactor: group dependency options together --- crates/cli/src/cli_command/add.rs | 85 ++++++++++++++++++------------- 1 file changed, 51 insertions(+), 34 deletions(-) diff --git a/crates/cli/src/cli_command/add.rs b/crates/cli/src/cli_command/add.rs index 8ea580890..b7a7f9b2f 100644 --- a/crates/cli/src/cli_command/add.rs +++ b/crates/cli/src/cli_command/add.rs @@ -4,10 +4,8 @@ use pacquet_package_json::DependencyGroup; use pacquet_package_manager::Install; use pacquet_registry::{PackageTag, PackageVersion}; -#[derive(Parser, Debug)] -pub struct AddArgs { - /// Name of the package - pub package: String, +#[derive(Debug, Parser)] +pub struct AddDependencyOptions { /// Install the specified packages as regular dependencies. #[arg(short = 'P', long = "save-prod", group = "dependency_group")] save_prod: bool, @@ -20,17 +18,9 @@ pub struct AddArgs { /// Using --save-peer will add one or more packages to peerDependencies and install them as dev dependencies #[arg(long = "save-peer", group = "dependency_group")] save_peer: bool, - /// Saved dependencies will be configured with an exact version rather than using - /// pacquet's default semver range operator. - #[arg(short = 'E', long = "save-exact")] - pub save_exact: bool, - /// The directory with links to the store (default is node_modules/.pacquet). - /// All direct and indirect dependencies of the project are linked into this directory - #[arg(long = "virtual-store-dir", default_value = "node_modules/.pacquet")] - pub virtual_store_dir: String, } -impl AddArgs { +impl AddDependencyOptions { pub fn dependency_group(&self) -> DependencyGroup { if self.save_dev { DependencyGroup::Dev @@ -44,6 +34,23 @@ impl AddArgs { } } +#[derive(Parser, Debug)] +pub struct AddArgs { + /// Name of the package + pub package: String, + /// --save-prod, --save-dev, --save-optional, --save-peer + #[clap(flatten)] + pub dependency_options: AddDependencyOptions, + /// Saved dependencies will be configured with an exact version rather than using + /// pacquet's default semver range operator. + #[arg(short = 'E', long = "save-exact")] + pub save_exact: bool, + /// The directory with links to the store (default is node_modules/.pacquet). + /// All direct and indirect dependencies of the project are linked into this directory + #[arg(long = "virtual-store-dir", default_value = "node_modules/.pacquet")] + pub virtual_store_dir: String, +} + impl PackageManager { pub async fn add(&mut self, args: &AddArgs) -> Result<(), PackageManagerError> { let PackageManager { config, package_json, lockfile, http_client, tarball_cache } = self; @@ -58,7 +65,7 @@ impl PackageManager { .expect("resolve latest tag"); // TODO: properly propagate this error let version_range = latest_version.serialize(args.save_exact); - let dependency_group = args.dependency_group(); + let dependency_group = args.dependency_options.dependency_group(); package_json .add_dependency(&args.package, &version_range, dependency_group) @@ -114,10 +121,12 @@ mod tests { let args = AddArgs { package: "is-even".to_string(), - save_prod: false, - save_dev: false, - save_peer: false, - save_optional: false, + dependency_options: AddDependencyOptions { + save_prod: false, + save_dev: false, + save_peer: false, + save_optional: false, + }, save_exact: false, virtual_store_dir: virtual_store_dir.to_string_lossy().to_string(), }; @@ -152,10 +161,12 @@ mod tests { let args = AddArgs { package: "is-odd".to_string(), - save_prod: false, - save_dev: false, - save_peer: false, - save_optional: false, + dependency_options: AddDependencyOptions { + save_prod: false, + save_dev: false, + save_peer: false, + save_optional: false, + }, save_exact: false, virtual_store_dir: virtual_store_dir.to_string_lossy().to_string(), }; @@ -183,10 +194,12 @@ mod tests { let args = AddArgs { package: "is-odd".to_string(), - save_prod: false, - save_dev: false, - save_peer: false, - save_optional: false, + dependency_options: AddDependencyOptions { + save_prod: false, + save_dev: false, + save_peer: false, + save_optional: false, + }, save_exact: false, virtual_store_dir: virtual_store_dir.to_string_lossy().to_string(), }; @@ -207,10 +220,12 @@ mod tests { let args = AddArgs { package: "is-odd".to_string(), - save_prod: false, - save_dev: true, - save_peer: false, - save_optional: false, + dependency_options: AddDependencyOptions { + save_prod: false, + save_dev: true, + save_peer: false, + save_optional: false, + }, save_exact: false, virtual_store_dir: virtual_store_dir.to_string_lossy().to_string(), }; @@ -231,10 +246,12 @@ mod tests { let args = AddArgs { package: "is-odd".to_string(), - save_prod: false, - save_dev: false, - save_peer: true, - save_optional: false, + dependency_options: AddDependencyOptions { + save_prod: false, + save_dev: false, + save_peer: true, + save_optional: false, + }, save_exact: false, virtual_store_dir: virtual_store_dir.to_string_lossy().to_string(), }; From 2e277dd1d89e9fbfcf02d6f28089eab55cf57e05 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 12:25:01 +0700 Subject: [PATCH 103/210] style: consistent derive order --- crates/cli/src/cli_command/add.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli/src/cli_command/add.rs b/crates/cli/src/cli_command/add.rs index b7a7f9b2f..a1467b9d6 100644 --- a/crates/cli/src/cli_command/add.rs +++ b/crates/cli/src/cli_command/add.rs @@ -34,7 +34,7 @@ impl AddDependencyOptions { } } -#[derive(Parser, Debug)] +#[derive(Debug, Parser)] pub struct AddArgs { /// Name of the package pub package: String, From ba691f1e61701a9419f6ace7920f2d257b9a2d02 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 12:26:23 +0700 Subject: [PATCH 104/210] style: consistent derive order --- crates/cli/src/cli_command/install.rs | 2 +- crates/cli/src/cli_command/mod.rs | 2 +- crates/cli/src/cli_command/run.rs | 2 +- crates/cli/src/cli_command/store.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/cli/src/cli_command/install.rs b/crates/cli/src/cli_command/install.rs index bb8010fa6..97b6359d9 100644 --- a/crates/cli/src/cli_command/install.rs +++ b/crates/cli/src/cli_command/install.rs @@ -36,7 +36,7 @@ impl InstallDependencyOptions { } } -#[derive(Parser, Debug)] +#[derive(Debug, Parser)] pub struct InstallArgs { /// --prod, --dev, and --no-optional #[clap(flatten)] diff --git a/crates/cli/src/cli_command/mod.rs b/crates/cli/src/cli_command/mod.rs index 8b5a294ad..0b1b9595e 100644 --- a/crates/cli/src/cli_command/mod.rs +++ b/crates/cli/src/cli_command/mod.rs @@ -15,7 +15,7 @@ fn default_current_dir() -> OsString { } /// Experimental package manager for node.js written in rust. -#[derive(Parser, Debug)] +#[derive(Debug, Parser)] #[command(name = "pacquet")] #[command(bin_name = "pacquet")] #[command(version = "0.2.1")] diff --git a/crates/cli/src/cli_command/run.rs b/crates/cli/src/cli_command/run.rs index 0cee83a1e..41a838b8a 100644 --- a/crates/cli/src/cli_command/run.rs +++ b/crates/cli/src/cli_command/run.rs @@ -1,6 +1,6 @@ use clap::Parser; -#[derive(Parser, Debug)] +#[derive(Debug, Parser)] pub struct RunArgs { /// A pre-defined package script. pub command: String, diff --git a/crates/cli/src/cli_command/store.rs b/crates/cli/src/cli_command/store.rs index 128baf077..26492bff5 100644 --- a/crates/cli/src/cli_command/store.rs +++ b/crates/cli/src/cli_command/store.rs @@ -1,6 +1,6 @@ use clap::Subcommand; -#[derive(Subcommand, Debug)] +#[derive(Debug, Subcommand)] pub enum StoreCommand { /// Checks for modified packages in the store. Store, From c3ab708c66214a06919cedb2fe9bd38ae7c8cdbe Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 12:27:27 +0700 Subject: [PATCH 105/210] style: use clap attribute --- crates/cli/src/cli_command/add.rs | 12 ++++++------ crates/cli/src/cli_command/mod.rs | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/crates/cli/src/cli_command/add.rs b/crates/cli/src/cli_command/add.rs index a1467b9d6..52301d7e1 100644 --- a/crates/cli/src/cli_command/add.rs +++ b/crates/cli/src/cli_command/add.rs @@ -7,16 +7,16 @@ use pacquet_registry::{PackageTag, PackageVersion}; #[derive(Debug, Parser)] pub struct AddDependencyOptions { /// Install the specified packages as regular dependencies. - #[arg(short = 'P', long = "save-prod", group = "dependency_group")] + #[clap(short = 'P', long = "save-prod", group = "dependency_group")] save_prod: bool, /// Install the specified packages as devDependencies. - #[arg(short = 'D', long = "save-dev", group = "dependency_group")] + #[clap(short = 'D', long = "save-dev", group = "dependency_group")] save_dev: bool, /// Install the specified packages as optionalDependencies. - #[arg(short = 'O', long = "save-optional", group = "dependency_group")] + #[clap(short = 'O', long = "save-optional", group = "dependency_group")] save_optional: bool, /// Using --save-peer will add one or more packages to peerDependencies and install them as dev dependencies - #[arg(long = "save-peer", group = "dependency_group")] + #[clap(long = "save-peer", group = "dependency_group")] save_peer: bool, } @@ -43,11 +43,11 @@ pub struct AddArgs { pub dependency_options: AddDependencyOptions, /// Saved dependencies will be configured with an exact version rather than using /// pacquet's default semver range operator. - #[arg(short = 'E', long = "save-exact")] + #[clap(short = 'E', long = "save-exact")] pub save_exact: bool, /// The directory with links to the store (default is node_modules/.pacquet). /// All direct and indirect dependencies of the project are linked into this directory - #[arg(long = "virtual-store-dir", default_value = "node_modules/.pacquet")] + #[clap(long = "virtual-store-dir", default_value = "node_modules/.pacquet")] pub virtual_store_dir: String, } diff --git a/crates/cli/src/cli_command/mod.rs b/crates/cli/src/cli_command/mod.rs index 0b1b9595e..a9b806ef8 100644 --- a/crates/cli/src/cli_command/mod.rs +++ b/crates/cli/src/cli_command/mod.rs @@ -16,16 +16,16 @@ fn default_current_dir() -> OsString { /// Experimental package manager for node.js written in rust. #[derive(Debug, Parser)] -#[command(name = "pacquet")] -#[command(bin_name = "pacquet")] -#[command(version = "0.2.1")] -#[command(about = "Experimental package manager for node.js")] +#[clap(name = "pacquet")] +#[clap(bin_name = "pacquet")] +#[clap(version = "0.2.1")] +#[clap(about = "Experimental package manager for node.js")] pub struct CliArgs { - #[command(subcommand)] + #[clap(subcommand)] pub command: CliCommand, /// Set working directory. - #[arg(short = 'C', long = "dir", default_value = default_current_dir())] + #[clap(short = 'C', long = "dir", default_value = default_current_dir())] pub dir: PathBuf, } From ab6fbd6bd80e8505607f72864accc65e1a72c2a5 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 12:41:45 +0700 Subject: [PATCH 106/210] refactor: use iterator to list dependency groups --- crates/cli/src/cli_command/add.rs | 35 +++++++++++++------------------ 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/crates/cli/src/cli_command/add.rs b/crates/cli/src/cli_command/add.rs index 52301d7e1..51bbb62ac 100644 --- a/crates/cli/src/cli_command/add.rs +++ b/crates/cli/src/cli_command/add.rs @@ -21,16 +21,17 @@ pub struct AddDependencyOptions { } impl AddDependencyOptions { - pub fn dependency_group(&self) -> DependencyGroup { - if self.save_dev { - DependencyGroup::Dev - } else if self.save_optional { - DependencyGroup::Optional - } else if self.save_peer { - DependencyGroup::Peer - } else { - DependencyGroup::Default - } + pub fn dependency_groups(&self) -> impl Iterator { + let &AddDependencyOptions { save_prod, save_dev, save_optional, save_peer } = self; + let has_prod = save_prod || (!save_dev && !save_optional && !save_peer); // no --save-* flags implies --save-prod + let has_dev = save_dev || (!save_prod && !save_optional && save_peer); // --save-peer with nothing else implies --save-dev + let has_optional = save_optional; + let has_peer = save_peer; + std::iter::empty() + .chain(has_prod.then_some(DependencyGroup::Default)) + .chain(has_dev.then_some(DependencyGroup::Dev)) + .chain(has_optional.then_some(DependencyGroup::Optional)) + .chain(has_peer.then_some(DependencyGroup::Peer)) } } @@ -65,17 +66,9 @@ impl PackageManager { .expect("resolve latest tag"); // TODO: properly propagate this error let version_range = latest_version.serialize(args.save_exact); - let dependency_group = args.dependency_options.dependency_group(); - - package_json - .add_dependency(&args.package, &version_range, dependency_group) - .map_err(PackageManagerError::PackageJson)?; - - // Using --save-peer will add one or more packages to peerDependencies and - // install them as dev dependencies - if dependency_group == DependencyGroup::Peer { + for dependency_group in args.dependency_options.dependency_groups() { package_json - .add_dependency(&args.package, &version_range, DependencyGroup::Dev) + .add_dependency(&args.package, &version_range, dependency_group) .map_err(PackageManagerError::PackageJson)?; } @@ -85,7 +78,7 @@ impl PackageManager { config, package_json, lockfile: lockfile.as_ref(), - dependency_groups: [dependency_group], + dependency_groups: args.dependency_options.dependency_groups(), frozen_lockfile: false, } .run() From 7cc6ffb026007450f34114e1c9a2b8eaa843d94a Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 12:43:12 +0700 Subject: [PATCH 107/210] docs: correction --- crates/cli/src/cli_command/install.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli/src/cli_command/install.rs b/crates/cli/src/cli_command/install.rs index 97b6359d9..8aab8d7d6 100644 --- a/crates/cli/src/cli_command/install.rs +++ b/crates/cli/src/cli_command/install.rs @@ -21,7 +21,7 @@ pub struct InstallDependencyOptions { } impl InstallDependencyOptions { - /// Convert the command arguments to an iterator of [`DependencyGroup`] + /// Convert the dependency options to an iterator of [`DependencyGroup`] /// which filters the types of dependencies to install. fn dependency_groups(&self) -> impl Iterator { let &InstallDependencyOptions { prod, dev, no_optional } = self; From 829041ccd473cb30d52be39f56164a113cf578a8 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 12:45:06 +0700 Subject: [PATCH 108/210] docs: AddDependencyOptions::dependency_groups --- crates/cli/src/cli_command/add.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/cli/src/cli_command/add.rs b/crates/cli/src/cli_command/add.rs index 51bbb62ac..e3a119640 100644 --- a/crates/cli/src/cli_command/add.rs +++ b/crates/cli/src/cli_command/add.rs @@ -21,6 +21,8 @@ pub struct AddDependencyOptions { } impl AddDependencyOptions { + /// Convert the `--save-*` flags to an iterator of [`DependencyGroup`] + /// which selects which target group to save to. pub fn dependency_groups(&self) -> impl Iterator { let &AddDependencyOptions { save_prod, save_dev, save_optional, save_peer } = self; let has_prod = save_prod || (!save_dev && !save_optional && !save_peer); // no --save-* flags implies --save-prod From 70833b981cbc2836f5ff524adbb25ad73d0187af Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 12:47:01 +0700 Subject: [PATCH 109/210] docs(test): correct a name --- crates/cli/src/cli_command/install.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli/src/cli_command/install.rs b/crates/cli/src/cli_command/install.rs index 8aab8d7d6..7026e52bd 100644 --- a/crates/cli/src/cli_command/install.rs +++ b/crates/cli/src/cli_command/install.rs @@ -76,7 +76,7 @@ mod tests { use pretty_assertions::assert_eq; #[test] - fn install_args_to_dependency_groups() { + fn dependency_options_to_dependency_groups() { use DependencyGroup::{Default, Dev, Optional}; let create_list = |opts: InstallDependencyOptions| opts.dependency_groups().collect::>(); From 93be4aaa6253a0fd8ba86f869ac50b14644625fe Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 13:14:21 +0700 Subject: [PATCH 110/210] test: AddDependencyOptions::dependency_groups --- crates/cli/src/cli_command/add.rs | 94 +++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/crates/cli/src/cli_command/add.rs b/crates/cli/src/cli_command/add.rs index e3a119640..651d9ec89 100644 --- a/crates/cli/src/cli_command/add.rs +++ b/crates/cli/src/cli_command/add.rs @@ -102,6 +102,100 @@ mod tests { use std::{env, fs}; use tempfile::tempdir; + #[test] + fn dependency_options_to_dependency_groups() { + use DependencyGroup::{Default, Dev, Optional, Peer}; + let create_list = |opts: AddDependencyOptions| opts.dependency_groups().collect::>(); + + // no flags -> prod + assert_eq!( + create_list(AddDependencyOptions { + save_prod: false, + save_dev: false, + save_optional: false, + save_peer: false + }), + [Default] + ); + + // --save-prod -> prod + assert_eq!( + create_list(AddDependencyOptions { + save_prod: true, + save_dev: false, + save_optional: false, + save_peer: false + }), + [Default] + ); + + // --save-dev -> dev + assert_eq!( + create_list(AddDependencyOptions { + save_prod: false, + save_dev: true, + save_optional: false, + save_peer: false + }), + [Dev] + ); + + // --save-optional -> optional + assert_eq!( + create_list(AddDependencyOptions { + save_prod: false, + save_dev: false, + save_optional: true, + save_peer: false + }), + [Optional] + ); + + // --save-peer -> dev + peer + assert_eq!( + create_list(AddDependencyOptions { + save_prod: false, + save_dev: false, + save_optional: false, + save_peer: true + }), + [Dev, Peer] + ); + + // --save-prod --save-peer -> prod + peer + assert_eq!( + create_list(AddDependencyOptions { + save_prod: true, + save_dev: false, + save_optional: false, + save_peer: true + }), + [Default, Peer] + ); + + // --save-dev --save-peer -> dev + peer + assert_eq!( + create_list(AddDependencyOptions { + save_prod: false, + save_dev: true, + save_optional: false, + save_peer: true + }), + [Dev, Peer] + ); + + // --save-optional --save-peer -> optional + peer + assert_eq!( + create_list(AddDependencyOptions { + save_prod: false, + save_dev: false, + save_optional: true, + save_peer: true + }), + [Optional, Peer] + ); + } + #[tokio::test] pub async fn should_install_all_dependencies() { let dir = tempdir().unwrap(); From 1c8a86bd05d23b52f6c2b9c0f8ac0119c19d06a4 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 13:19:28 +0700 Subject: [PATCH 111/210] refactor: derive less --- crates/cli/src/cli_command/add.rs | 6 +++--- crates/cli/src/cli_command/install.rs | 6 +++--- crates/cli/src/cli_command/run.rs | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/cli/src/cli_command/add.rs b/crates/cli/src/cli_command/add.rs index 651d9ec89..6602c8260 100644 --- a/crates/cli/src/cli_command/add.rs +++ b/crates/cli/src/cli_command/add.rs @@ -1,10 +1,10 @@ use crate::package_manager::{PackageManager, PackageManagerError}; -use clap::Parser; +use clap::Args; use pacquet_package_json::DependencyGroup; use pacquet_package_manager::Install; use pacquet_registry::{PackageTag, PackageVersion}; -#[derive(Debug, Parser)] +#[derive(Debug, Args)] pub struct AddDependencyOptions { /// Install the specified packages as regular dependencies. #[clap(short = 'P', long = "save-prod", group = "dependency_group")] @@ -37,7 +37,7 @@ impl AddDependencyOptions { } } -#[derive(Debug, Parser)] +#[derive(Debug, Args)] pub struct AddArgs { /// Name of the package pub package: String, diff --git a/crates/cli/src/cli_command/install.rs b/crates/cli/src/cli_command/install.rs index 7026e52bd..3820b7a50 100644 --- a/crates/cli/src/cli_command/install.rs +++ b/crates/cli/src/cli_command/install.rs @@ -1,9 +1,9 @@ use crate::package_manager::{PackageManager, PackageManagerError}; -use clap::Parser; +use clap::Args; use pacquet_package_json::DependencyGroup; use pacquet_package_manager::Install; -#[derive(Debug, Parser)] +#[derive(Debug, Args)] pub struct InstallDependencyOptions { /// pacquet will not install any package listed in devDependencies and will remove those insofar /// they were already installed, if the NODE_ENV environment variable is set to production. @@ -36,7 +36,7 @@ impl InstallDependencyOptions { } } -#[derive(Debug, Parser)] +#[derive(Debug, Args)] pub struct InstallArgs { /// --prod, --dev, and --no-optional #[clap(flatten)] diff --git a/crates/cli/src/cli_command/run.rs b/crates/cli/src/cli_command/run.rs index 41a838b8a..c925d38cb 100644 --- a/crates/cli/src/cli_command/run.rs +++ b/crates/cli/src/cli_command/run.rs @@ -1,6 +1,6 @@ -use clap::Parser; +use clap::Args; -#[derive(Debug, Parser)] +#[derive(Debug, Args)] pub struct RunArgs { /// A pre-defined package script. pub command: String, From ed78c9dd2a3622cb8ebfd5158a1a36e48d824f9b Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 13:22:15 +0700 Subject: [PATCH 112/210] refactor: stop using `mod.rs` --- crates/cli/src/{cli_command/mod.rs => cli_command.rs} | 0 tasks/integrated-benchmark/src/fixtures.rs | 2 ++ tasks/integrated-benchmark/src/fixtures/mod.rs | 2 -- 3 files changed, 2 insertions(+), 2 deletions(-) rename crates/cli/src/{cli_command/mod.rs => cli_command.rs} (100%) create mode 100644 tasks/integrated-benchmark/src/fixtures.rs delete mode 100644 tasks/integrated-benchmark/src/fixtures/mod.rs diff --git a/crates/cli/src/cli_command/mod.rs b/crates/cli/src/cli_command.rs similarity index 100% rename from crates/cli/src/cli_command/mod.rs rename to crates/cli/src/cli_command.rs diff --git a/tasks/integrated-benchmark/src/fixtures.rs b/tasks/integrated-benchmark/src/fixtures.rs new file mode 100644 index 000000000..d998722fb --- /dev/null +++ b/tasks/integrated-benchmark/src/fixtures.rs @@ -0,0 +1,2 @@ +pub const PACKAGE_JSON: &str = include_str!("fixtures/package.json"); +pub const LOCKFILE: &str = include_str!("fixtures/pnpm-lock.yaml"); diff --git a/tasks/integrated-benchmark/src/fixtures/mod.rs b/tasks/integrated-benchmark/src/fixtures/mod.rs deleted file mode 100644 index 9b8b287d2..000000000 --- a/tasks/integrated-benchmark/src/fixtures/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub const PACKAGE_JSON: &str = include_str!("package.json"); -pub const LOCKFILE: &str = include_str!("pnpm-lock.yaml"); From 9048ccee31ef66aa5fc702d1e69b4ea9d1956846 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 13:24:02 +0700 Subject: [PATCH 113/210] style(test): remove unnecessary pub --- crates/cli/src/cli_command/add.rs | 6 +++--- crates/package_manager/src/install.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/cli/src/cli_command/add.rs b/crates/cli/src/cli_command/add.rs index 6602c8260..26cf8a26b 100644 --- a/crates/cli/src/cli_command/add.rs +++ b/crates/cli/src/cli_command/add.rs @@ -273,7 +273,7 @@ mod tests { } #[tokio::test] - pub async fn should_add_to_package_json() { + async fn should_add_to_package_json() { let dir = tempdir().unwrap(); let virtual_store_dir = dir.path().join("node_modules/.pacquet"); let current_directory = env::current_dir().unwrap(); @@ -299,7 +299,7 @@ mod tests { } #[tokio::test] - pub async fn should_add_dev_dependency() { + async fn should_add_dev_dependency() { let dir = tempdir().unwrap(); let virtual_store_dir = dir.path().join("node_modules/.pacquet"); let current_directory = env::current_dir().unwrap(); @@ -325,7 +325,7 @@ mod tests { } #[tokio::test] - pub async fn should_add_peer_dependency() { + async fn should_add_peer_dependency() { let dir = tempdir().unwrap(); let virtual_store_dir = dir.path().join("node_modules/.pacquet"); let current_directory = env::current_dir().unwrap(); diff --git a/crates/package_manager/src/install.rs b/crates/package_manager/src/install.rs index 5043cf27b..90cffc670 100644 --- a/crates/package_manager/src/install.rs +++ b/crates/package_manager/src/install.rs @@ -91,7 +91,7 @@ mod tests { use tempfile::tempdir; #[tokio::test] - pub async fn should_install_dependencies() { + async fn should_install_dependencies() { let dir = tempdir().unwrap(); let store_dir = dir.path().join("pacquet-store"); let project_root = dir.path().join("project"); From 6e75b1f4918e940e0d28e4ffe74880973d65450e Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 13:24:23 +0700 Subject: [PATCH 114/210] refactor: make dependency_groups private --- crates/cli/src/cli_command/add.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli/src/cli_command/add.rs b/crates/cli/src/cli_command/add.rs index 26cf8a26b..38d0d7112 100644 --- a/crates/cli/src/cli_command/add.rs +++ b/crates/cli/src/cli_command/add.rs @@ -23,7 +23,7 @@ pub struct AddDependencyOptions { impl AddDependencyOptions { /// Convert the `--save-*` flags to an iterator of [`DependencyGroup`] /// which selects which target group to save to. - pub fn dependency_groups(&self) -> impl Iterator { + fn dependency_groups(&self) -> impl Iterator { let &AddDependencyOptions { save_prod, save_dev, save_optional, save_peer } = self; let has_prod = save_prod || (!save_dev && !save_optional && !save_peer); // no --save-* flags implies --save-prod let has_dev = save_dev || (!save_prod && !save_optional && save_peer); // --save-peer with nothing else implies --save-dev From 3efa05de27e4e57ab28db511f58b9d1387a26e6a Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 13:42:40 +0700 Subject: [PATCH 115/210] refactor(cli): remove explicit longs --- crates/cli/src/cli_command.rs | 2 +- crates/cli/src/cli_command/add.rs | 8 ++++---- crates/cli/src/cli_command/install.rs | 6 +++--- crates/cli/src/cli_command/run.rs | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/cli/src/cli_command.rs b/crates/cli/src/cli_command.rs index a9b806ef8..049753d1f 100644 --- a/crates/cli/src/cli_command.rs +++ b/crates/cli/src/cli_command.rs @@ -25,7 +25,7 @@ pub struct CliArgs { pub command: CliCommand, /// Set working directory. - #[clap(short = 'C', long = "dir", default_value = default_current_dir())] + #[clap(short = 'C', long, default_value = default_current_dir())] pub dir: PathBuf, } diff --git a/crates/cli/src/cli_command/add.rs b/crates/cli/src/cli_command/add.rs index 38d0d7112..b9a70ef5f 100644 --- a/crates/cli/src/cli_command/add.rs +++ b/crates/cli/src/cli_command/add.rs @@ -7,16 +7,16 @@ use pacquet_registry::{PackageTag, PackageVersion}; #[derive(Debug, Args)] pub struct AddDependencyOptions { /// Install the specified packages as regular dependencies. - #[clap(short = 'P', long = "save-prod", group = "dependency_group")] + #[clap(short = 'P', long, group = "dependency_group")] save_prod: bool, /// Install the specified packages as devDependencies. - #[clap(short = 'D', long = "save-dev", group = "dependency_group")] + #[clap(short = 'D', long, group = "dependency_group")] save_dev: bool, /// Install the specified packages as optionalDependencies. - #[clap(short = 'O', long = "save-optional", group = "dependency_group")] + #[clap(short = 'O', long, group = "dependency_group")] save_optional: bool, /// Using --save-peer will add one or more packages to peerDependencies and install them as dev dependencies - #[clap(long = "save-peer", group = "dependency_group")] + #[clap(long, group = "dependency_group")] save_peer: bool, } diff --git a/crates/cli/src/cli_command/install.rs b/crates/cli/src/cli_command/install.rs index 3820b7a50..6fe15dd17 100644 --- a/crates/cli/src/cli_command/install.rs +++ b/crates/cli/src/cli_command/install.rs @@ -9,14 +9,14 @@ pub struct InstallDependencyOptions { /// they were already installed, if the NODE_ENV environment variable is set to production. /// Use this flag to instruct pacquet to ignore NODE_ENV and take its production status from this /// flag instead. - #[arg(short = 'P', long = "prod")] + #[arg(short = 'P', long)] pub prod: bool, /// Only devDependencies are installed and dependencies are removed insofar they were /// already installed, regardless of the NODE_ENV. - #[arg(short = 'D', long = "dev")] + #[arg(short = 'D', long)] pub dev: bool, /// optionalDependencies are not installed. - #[arg(long = "no-optional")] + #[arg(long)] pub no_optional: bool, } diff --git a/crates/cli/src/cli_command/run.rs b/crates/cli/src/cli_command/run.rs index c925d38cb..69f656918 100644 --- a/crates/cli/src/cli_command/run.rs +++ b/crates/cli/src/cli_command/run.rs @@ -11,6 +11,6 @@ pub struct RunArgs { /// You can use the --if-present flag to avoid exiting with a non-zero exit code when the /// script is undefined. This lets you run potentially undefined scripts without breaking the /// execution chain. - #[arg(long = "if-present")] + #[arg(long)] pub if_present: bool, } From 206b705d1aab4bb69db60ff658772b6738d81fdc Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 13:43:15 +0700 Subject: [PATCH 116/210] refactor(cli): use clap attribute --- crates/cli/src/cli_command/run.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli/src/cli_command/run.rs b/crates/cli/src/cli_command/run.rs index 69f656918..378179aa5 100644 --- a/crates/cli/src/cli_command/run.rs +++ b/crates/cli/src/cli_command/run.rs @@ -11,6 +11,6 @@ pub struct RunArgs { /// You can use the --if-present flag to avoid exiting with a non-zero exit code when the /// script is undefined. This lets you run potentially undefined scripts without breaking the /// execution chain. - #[arg(long)] + #[clap(long)] pub if_present: bool, } From 6e3ff87a10b247fa4587b3cc159ebd37aa2bed00 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 13:50:44 +0700 Subject: [PATCH 117/210] feat(cli): don't eagerly call current_dir --- crates/cli/src/cli_command.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/crates/cli/src/cli_command.rs b/crates/cli/src/cli_command.rs index 049753d1f..fab2a0726 100644 --- a/crates/cli/src/cli_command.rs +++ b/crates/cli/src/cli_command.rs @@ -7,13 +7,9 @@ use add::AddArgs; use clap::{Parser, Subcommand}; use install::InstallArgs; use run::RunArgs; -use std::{env, ffi::OsString, path::PathBuf}; +use std::path::PathBuf; use store::StoreCommand; -fn default_current_dir() -> OsString { - env::current_dir().expect("failed to get current directory").into_os_string() -} - /// Experimental package manager for node.js written in rust. #[derive(Debug, Parser)] #[clap(name = "pacquet")] @@ -25,7 +21,7 @@ pub struct CliArgs { pub command: CliCommand, /// Set working directory. - #[clap(short = 'C', long, default_value = default_current_dir())] + #[clap(short = 'C', long, default_value = ".")] pub dir: PathBuf, } From 90e45a7689d39a171704725149769d7d59a27601 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 16:37:54 +0700 Subject: [PATCH 118/210] refactor: move some code --- crates/cli/src/cli_command/add.rs | 31 +++------- crates/package_manager/src/add.rs | 96 +++++++++++++++++++++++++++++++ crates/package_manager/src/lib.rs | 2 + 3 files changed, 105 insertions(+), 24 deletions(-) create mode 100644 crates/package_manager/src/add.rs diff --git a/crates/cli/src/cli_command/add.rs b/crates/cli/src/cli_command/add.rs index b9a70ef5f..a06a07c20 100644 --- a/crates/cli/src/cli_command/add.rs +++ b/crates/cli/src/cli_command/add.rs @@ -1,8 +1,7 @@ use crate::package_manager::{PackageManager, PackageManagerError}; use clap::Args; use pacquet_package_json::DependencyGroup; -use pacquet_package_manager::Install; -use pacquet_registry::{PackageTag, PackageVersion}; +use pacquet_package_manager::Add; #[derive(Debug, Args)] pub struct AddDependencyOptions { @@ -58,35 +57,19 @@ impl PackageManager { pub async fn add(&mut self, args: &AddArgs) -> Result<(), PackageManagerError> { let PackageManager { config, package_json, lockfile, http_client, tarball_cache } = self; - let latest_version = PackageVersion::fetch_from_registry( - &args.package, - PackageTag::Latest, // TODO: add support for specifying tags - http_client, - &config.registry, - ) - .await - .expect("resolve latest tag"); // TODO: properly propagate this error - - let version_range = latest_version.serialize(args.save_exact); - for dependency_group in args.dependency_options.dependency_groups() { - package_json - .add_dependency(&args.package, &version_range, dependency_group) - .map_err(PackageManagerError::PackageJson)?; - } - - Install { + Add { tarball_cache, http_client, config, package_json, lockfile: lockfile.as_ref(), - dependency_groups: args.dependency_options.dependency_groups(), - frozen_lockfile: false, + list_dependency_groups: || args.dependency_options.dependency_groups(), + package: &args.package, + save_exact: args.save_exact, } .run() - .await; - - package_json.save().map_err(PackageManagerError::PackageJson)?; + .await + .unwrap(); Ok(()) } diff --git a/crates/package_manager/src/add.rs b/crates/package_manager/src/add.rs new file mode 100644 index 000000000..98828101c --- /dev/null +++ b/crates/package_manager/src/add.rs @@ -0,0 +1,96 @@ +use crate::Install; +use derive_more::{Display, Error}; +use miette::Diagnostic; +use pacquet_lockfile::Lockfile; +use pacquet_npmrc::Npmrc; +use pacquet_package_json::PackageJsonError; +use pacquet_package_json::{DependencyGroup, PackageJson}; +use pacquet_registry::{PackageTag, PackageVersion}; +use pacquet_tarball::Cache; +use reqwest::Client; + +/// Error type of [`Add`]. +#[derive(Debug, Display, Error, Diagnostic)] +pub enum AddError { + #[display(fmt = "Failed to add package to manifest: {_0}")] + AddDependencyToPackageJson(#[error(source)] PackageJsonError), + #[display(fmt = "Failed save the manifest file: {_0}")] + SavePackageJson(#[error(source)] PackageJsonError), +} + +/// This subroutine does everything `pacquet add` is supposed to do. +#[must_use] +pub struct Add<'a, ListDependencyGroups, DependencyGroupList> +where + ListDependencyGroups: Fn() -> DependencyGroupList, + DependencyGroupList: IntoIterator, +{ + /// Shared cache that store downloaded tarballs. + pub tarball_cache: &'a Cache, + /// HTTP client to make HTTP requests. + pub http_client: &'a Client, + /// Configuration read from `.npmrc`. + pub config: &'static Npmrc, + /// Data from the `package.json` file. + pub package_json: &'a mut PackageJson, + /// Data from the `pnpm-lock.yaml` file. + pub lockfile: Option<&'a Lockfile>, + /// List of [`DependencyGroup`]s. + pub list_dependency_groups: ListDependencyGroups, + /// Name of the package to add. + pub package: &'a str, + /// Whether `--save-exact` is provided. + pub save_exact: bool, +} + +impl<'a, ListDependencyGroups, DependencyGroupList> + Add<'a, ListDependencyGroups, DependencyGroupList> +where + ListDependencyGroups: Fn() -> DependencyGroupList, + DependencyGroupList: IntoIterator, +{ + pub async fn run(self) -> Result<(), AddError> { + let Add { + tarball_cache, + http_client, + config, + package_json, + lockfile, + list_dependency_groups, + package, + save_exact, + } = self; + + let latest_version = PackageVersion::fetch_from_registry( + package, + PackageTag::Latest, // TODO: add support for specifying tags + http_client, + &config.registry, + ) + .await + .expect("resolve latest tag"); // TODO: properly propagate this error + + let version_range = latest_version.serialize(save_exact); + for dependency_group in list_dependency_groups() { + package_json + .add_dependency(package, &version_range, dependency_group) + .map_err(AddError::AddDependencyToPackageJson)?; + } + + Install { + tarball_cache, + http_client, + config, + package_json, + lockfile, + dependency_groups: list_dependency_groups(), + frozen_lockfile: false, + } + .run() + .await; + + package_json.save().map_err(AddError::SavePackageJson)?; + + Ok(()) + } +} diff --git a/crates/package_manager/src/lib.rs b/crates/package_manager/src/lib.rs index 18290c000..654bd9cb3 100644 --- a/crates/package_manager/src/lib.rs +++ b/crates/package_manager/src/lib.rs @@ -1,3 +1,4 @@ +mod add; mod create_cas_files; mod create_symlink_layout; mod create_virtual_dir_by_snapshot; @@ -11,6 +12,7 @@ mod link_file; mod symlink_direct_dependencies; mod symlink_package; +pub use add::*; pub use create_cas_files::*; pub use create_symlink_layout::*; pub use create_virtual_dir_by_snapshot::*; From 3604c98849293d98df4d4d41042d93faacc296b4 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 16:40:32 +0700 Subject: [PATCH 119/210] refactor: move error types closer to their users --- crates/package_manager/src/add.rs | 18 +++++------ .../src/create_virtual_dir_by_snapshot.rs | 30 +++++++++---------- .../src/install_package_by_snapshot.rs | 14 ++++----- .../src/install_package_from_registry.rs | 18 +++++------ 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/crates/package_manager/src/add.rs b/crates/package_manager/src/add.rs index 98828101c..38ab3ccaa 100644 --- a/crates/package_manager/src/add.rs +++ b/crates/package_manager/src/add.rs @@ -9,15 +9,6 @@ use pacquet_registry::{PackageTag, PackageVersion}; use pacquet_tarball::Cache; use reqwest::Client; -/// Error type of [`Add`]. -#[derive(Debug, Display, Error, Diagnostic)] -pub enum AddError { - #[display(fmt = "Failed to add package to manifest: {_0}")] - AddDependencyToPackageJson(#[error(source)] PackageJsonError), - #[display(fmt = "Failed save the manifest file: {_0}")] - SavePackageJson(#[error(source)] PackageJsonError), -} - /// This subroutine does everything `pacquet add` is supposed to do. #[must_use] pub struct Add<'a, ListDependencyGroups, DependencyGroupList> @@ -43,6 +34,15 @@ where pub save_exact: bool, } +/// Error type of [`Add`]. +#[derive(Debug, Display, Error, Diagnostic)] +pub enum AddError { + #[display(fmt = "Failed to add package to manifest: {_0}")] + AddDependencyToPackageJson(#[error(source)] PackageJsonError), + #[display(fmt = "Failed save the manifest file: {_0}")] + SavePackageJson(#[error(source)] PackageJsonError), +} + impl<'a, ListDependencyGroups, DependencyGroupList> Add<'a, ListDependencyGroups, DependencyGroupList> where diff --git a/crates/package_manager/src/create_virtual_dir_by_snapshot.rs b/crates/package_manager/src/create_virtual_dir_by_snapshot.rs index 6ce98094c..f357ac4d1 100644 --- a/crates/package_manager/src/create_virtual_dir_by_snapshot.rs +++ b/crates/package_manager/src/create_virtual_dir_by_snapshot.rs @@ -10,21 +10,6 @@ use std::{ path::{Path, PathBuf}, }; -/// Error type of [`CreateVirtualDirBySnapshot`]. -#[derive(Debug, Display, Error, Diagnostic)] -pub enum CreateVirtualDirError { - #[display(fmt = "Failed to recursively create node_modules directory at {dir:?}: {error}")] - #[diagnostic(code(pacquet_package_manager::create_node_modules_dir))] - CreateNodeModulesDir { - dir: PathBuf, - #[error(source)] - error: io::Error, - }, - - #[diagnostic(transparent)] - CreateCasFiles(#[error(source)] CreateCasFilesError), -} - /// This subroutine installs the files from [`cas_paths`](Self::cas_paths) then creates the symlink layout. #[must_use] pub struct CreateVirtualDirBySnapshot<'a> { @@ -40,6 +25,21 @@ pub struct CreateVirtualDirBySnapshot<'a> { pub package_snapshot: &'a PackageSnapshot, } +/// Error type of [`CreateVirtualDirBySnapshot`]. +#[derive(Debug, Display, Error, Diagnostic)] +pub enum CreateVirtualDirError { + #[display(fmt = "Failed to recursively create node_modules directory at {dir:?}: {error}")] + #[diagnostic(code(pacquet_package_manager::create_node_modules_dir))] + CreateNodeModulesDir { + dir: PathBuf, + #[error(source)] + error: io::Error, + }, + + #[diagnostic(transparent)] + CreateCasFiles(#[error(source)] CreateCasFilesError), +} + impl<'a> CreateVirtualDirBySnapshot<'a> { /// Execute the subroutine. pub fn run(self) -> Result<(), CreateVirtualDirError> { diff --git a/crates/package_manager/src/install_package_by_snapshot.rs b/crates/package_manager/src/install_package_by_snapshot.rs index 7422c969b..0780a8b6d 100644 --- a/crates/package_manager/src/install_package_by_snapshot.rs +++ b/crates/package_manager/src/install_package_by_snapshot.rs @@ -8,13 +8,6 @@ use pipe_trait::Pipe; use reqwest::Client; use std::borrow::Cow; -/// Error type of [`InstallPackageBySnapshot`]. -#[derive(Debug, Display, Error, Diagnostic)] -pub enum InstallPackageBySnapshotError { - DownloadTarball(TarballError), - CreateVirtualDir(CreateVirtualDirError), -} - /// This subroutine downloads a package tarball, extracts it, installs it to a virtual dir, /// then creates the symlink layout for the package. #[must_use] @@ -31,6 +24,13 @@ pub struct InstallPackageBySnapshot<'a> { pub package_snapshot: &'a PackageSnapshot, } +/// Error type of [`InstallPackageBySnapshot`]. +#[derive(Debug, Display, Error, Diagnostic)] +pub enum InstallPackageBySnapshotError { + DownloadTarball(TarballError), + CreateVirtualDir(CreateVirtualDirError), +} + impl<'a> InstallPackageBySnapshot<'a> { /// Execute the subroutine. pub async fn run(self) -> Result<(), InstallPackageBySnapshotError> { diff --git a/crates/package_manager/src/install_package_from_registry.rs b/crates/package_manager/src/install_package_from_registry.rs index 708c33be1..1e0613273 100644 --- a/crates/package_manager/src/install_package_from_registry.rs +++ b/crates/package_manager/src/install_package_from_registry.rs @@ -7,15 +7,6 @@ use pacquet_tarball::{download_tarball_to_store, Cache, TarballError}; use reqwest::Client; use std::{path::Path, str::FromStr}; -/// Error type of [`InstallPackageFromRegistry`]. -#[derive(Debug, Display, Error, Diagnostic)] -pub enum InstallPackageFromRegistryError { - FetchFromRegistry(#[error(source)] RegistryError), - DownloadTarballToStore(#[error(source)] TarballError), - CreateCasFiles(#[error(source)] CreateCasFilesError), - SymlinkPackage(#[error(source)] SymlinkPackageError), -} - /// This subroutine executes the following and returns the package /// * Retrieves the package from the registry /// * Extracts the tarball to global store directory (~/Library/../pacquet) @@ -40,6 +31,15 @@ pub struct InstallPackageFromRegistry<'a> { pub version_range: &'a str, } +/// Error type of [`InstallPackageFromRegistry`]. +#[derive(Debug, Display, Error, Diagnostic)] +pub enum InstallPackageFromRegistryError { + FetchFromRegistry(#[error(source)] RegistryError), + DownloadTarballToStore(#[error(source)] TarballError), + CreateCasFiles(#[error(source)] CreateCasFilesError), + SymlinkPackage(#[error(source)] SymlinkPackageError), +} + impl<'a> InstallPackageFromRegistry<'a> { /// Execute the subroutine. pub async fn run(self) -> Result From 436356af8d99983af34aa3e5bcc6b6d1ac4c861a Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 16:42:56 +0700 Subject: [PATCH 120/210] refactor: remove unused clap groups --- crates/cli/src/cli_command/add.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/cli/src/cli_command/add.rs b/crates/cli/src/cli_command/add.rs index a06a07c20..32cc92db2 100644 --- a/crates/cli/src/cli_command/add.rs +++ b/crates/cli/src/cli_command/add.rs @@ -6,16 +6,16 @@ use pacquet_package_manager::Add; #[derive(Debug, Args)] pub struct AddDependencyOptions { /// Install the specified packages as regular dependencies. - #[clap(short = 'P', long, group = "dependency_group")] + #[clap(short = 'P', long)] save_prod: bool, /// Install the specified packages as devDependencies. - #[clap(short = 'D', long, group = "dependency_group")] + #[clap(short = 'D', long)] save_dev: bool, /// Install the specified packages as optionalDependencies. - #[clap(short = 'O', long, group = "dependency_group")] + #[clap(short = 'O', long)] save_optional: bool, /// Using --save-peer will add one or more packages to peerDependencies and install them as dev dependencies - #[clap(long, group = "dependency_group")] + #[clap(long)] save_peer: bool, } From ccdea75ac300282be5123ad6e443e22ad0e8a18a Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 16:50:28 +0700 Subject: [PATCH 121/210] refactor: rename error variants --- crates/cli/src/package_manager.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/cli/src/package_manager.rs b/crates/cli/src/package_manager.rs index 07ccaea4d..cc6c14637 100644 --- a/crates/cli/src/package_manager.rs +++ b/crates/cli/src/package_manager.rs @@ -15,11 +15,11 @@ use pipe_trait::Pipe; pub enum PackageManagerError { #[error(transparent)] #[diagnostic(transparent)] - PackageJson(pacquet_package_json::PackageJsonError), + LoadPackageJson(pacquet_package_json::PackageJsonError), #[error(transparent)] #[diagnostic(transparent)] - LoadLockfileError(pacquet_lockfile::LoadLockfileError), + LoadLockfile(pacquet_lockfile::LoadLockfileError), } pub struct PackageManager { @@ -40,9 +40,9 @@ impl PackageManager { package_json: package_json_path .into() .pipe(PackageJson::create_if_needed) - .map_err(PackageManagerError::PackageJson)?, + .map_err(PackageManagerError::LoadPackageJson)?, lockfile: call_load_lockfile(config.lockfile, Lockfile::load_from_current_dir) - .map_err(PackageManagerError::LoadLockfileError)?, + .map_err(PackageManagerError::LoadLockfile)?, http_client: reqwest::Client::new(), tarball_cache: Cache::new(), }) From e4fa7c41a54f883f6df13822684a6725f2e16d05 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 16:52:41 +0700 Subject: [PATCH 122/210] feat(cli): propagate an error --- crates/cli/src/cli_command/add.rs | 4 +--- crates/cli/src/package_manager.rs | 4 ++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/cli/src/cli_command/add.rs b/crates/cli/src/cli_command/add.rs index 32cc92db2..4d73f8961 100644 --- a/crates/cli/src/cli_command/add.rs +++ b/crates/cli/src/cli_command/add.rs @@ -69,9 +69,7 @@ impl PackageManager { } .run() .await - .unwrap(); - - Ok(()) + .map_err(PackageManagerError::AddCommand) } } diff --git a/crates/cli/src/package_manager.rs b/crates/cli/src/package_manager.rs index cc6c14637..0ab392da9 100644 --- a/crates/cli/src/package_manager.rs +++ b/crates/cli/src/package_manager.rs @@ -20,6 +20,10 @@ pub enum PackageManagerError { #[error(transparent)] #[diagnostic(transparent)] LoadLockfile(pacquet_lockfile::LoadLockfileError), + + #[error(transparent)] + #[diagnostic(transparent)] + AddCommand(pacquet_package_manager::AddError), } pub struct PackageManager { From 77b64bd7ea66c0a4caa6b09b42c79b447296799f Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 16:53:27 +0700 Subject: [PATCH 123/210] style: prefer use statements --- crates/cli/src/package_manager.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/cli/src/package_manager.rs b/crates/cli/src/package_manager.rs index 0ab392da9..df13f12aa 100644 --- a/crates/cli/src/package_manager.rs +++ b/crates/cli/src/package_manager.rs @@ -4,9 +4,10 @@ use pacquet_diagnostics::{ miette::{self, Diagnostic}, thiserror::{self, Error}, }; -use pacquet_lockfile::Lockfile; +use pacquet_lockfile::{LoadLockfileError, Lockfile}; use pacquet_npmrc::Npmrc; -use pacquet_package_json::PackageJson; +use pacquet_package_json::{PackageJson, PackageJsonError}; +use pacquet_package_manager::AddError; use pacquet_tarball::Cache; use pipe_trait::Pipe; @@ -15,15 +16,15 @@ use pipe_trait::Pipe; pub enum PackageManagerError { #[error(transparent)] #[diagnostic(transparent)] - LoadPackageJson(pacquet_package_json::PackageJsonError), + LoadPackageJson(PackageJsonError), #[error(transparent)] #[diagnostic(transparent)] - LoadLockfile(pacquet_lockfile::LoadLockfileError), + LoadLockfile(LoadLockfileError), #[error(transparent)] #[diagnostic(transparent)] - AddCommand(pacquet_package_manager::AddError), + AddCommand(AddError), } pub struct PackageManager { From 232cae69732c3e5e56e45aac91d00a37346d2c3c Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 16:53:43 +0700 Subject: [PATCH 124/210] style: merge imports --- crates/cli/src/package_manager.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/cli/src/package_manager.rs b/crates/cli/src/package_manager.rs index df13f12aa..42d9b5de3 100644 --- a/crates/cli/src/package_manager.rs +++ b/crates/cli/src/package_manager.rs @@ -1,5 +1,3 @@ -use std::path::PathBuf; - use pacquet_diagnostics::{ miette::{self, Diagnostic}, thiserror::{self, Error}, @@ -10,6 +8,7 @@ use pacquet_package_json::{PackageJson, PackageJsonError}; use pacquet_package_manager::AddError; use pacquet_tarball::Cache; use pipe_trait::Pipe; +use std::path::PathBuf; #[derive(Error, Debug, Diagnostic)] #[non_exhaustive] From e4d66fe0bd064aa182007126ca0d9112d541cafe Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 16:56:45 +0700 Subject: [PATCH 125/210] chore(cargo): remove unused dependencies --- Cargo.lock | 8 -------- crates/cli/Cargo.toml | 16 ++++------------ 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f576aed21..684a86dbb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1260,11 +1260,8 @@ dependencies = [ name = "pacquet_cli" version = "0.0.1" dependencies = [ - "async-recursion", "clap", - "futures-util", "insta", - "node-semver", "pacquet_cafs", "pacquet_diagnostics", "pacquet_executor", @@ -1278,14 +1275,9 @@ dependencies = [ "pacquet_testing_utils", "pipe-trait", "pretty_assertions", - "rayon", - "reflink-copy", "reqwest", - "serde", - "serde_json", "tempfile", "tokio", - "walkdir", ] [[package]] diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 583fda692..c2a52be59 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -26,17 +26,10 @@ pacquet_registry = { workspace = true } pacquet_tarball = { workspace = true } pacquet_diagnostics = { workspace = true } -async-recursion = { workspace = true } -clap = { workspace = true } -futures-util = { workspace = true } -rayon = { workspace = true } -reflink-copy = { workspace = true } -reqwest = { workspace = true } -node-semver = { workspace = true } -pipe-trait = { workspace = true } -serde = { workspace = true } -serde_json = { workspace = true } -tokio = { workspace = true } +clap = { workspace = true } +reqwest = { workspace = true } +pipe-trait = { workspace = true } +tokio = { workspace = true } [dev-dependencies] pacquet_testing_utils = { workspace = true } @@ -44,4 +37,3 @@ pacquet_testing_utils = { workspace = true } insta = { workspace = true } pretty_assertions = { workspace = true } tempfile = { workspace = true } -walkdir = { workspace = true } From efc2068f71bf69c4728473a3cdafeb12c11f3b69 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 18:18:22 +0700 Subject: [PATCH 126/210] refactor(cli): import directly --- Cargo.lock | 3 +++ crates/cli/Cargo.toml | 3 +++ crates/cli/src/lib.rs | 10 ++++------ crates/cli/src/package_manager.rs | 6 ++---- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 684a86dbb..5844d5bda 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1262,6 +1262,7 @@ version = "0.0.1" dependencies = [ "clap", "insta", + "miette", "pacquet_cafs", "pacquet_diagnostics", "pacquet_executor", @@ -1277,7 +1278,9 @@ dependencies = [ "pretty_assertions", "reqwest", "tempfile", + "thiserror", "tokio", + "tracing", ] [[package]] diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index c2a52be59..9f935795c 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -27,9 +27,12 @@ pacquet_tarball = { workspace = true } pacquet_diagnostics = { workspace = true } clap = { workspace = true } +miette = { workspace = true } reqwest = { workspace = true } pipe-trait = { workspace = true } +thiserror = { workspace = true } tokio = { workspace = true } +tracing = { workspace = true } [dev-dependencies] pacquet_testing_utils = { workspace = true } diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index e60f51f7e..b94f041df 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -3,16 +3,14 @@ mod package_manager; use clap::Parser; use cli_command::{store::StoreCommand, CliArgs, CliCommand}; +use miette::{set_panic_hook, Context, IntoDiagnostic}; use package_manager::PackageManager; -use pacquet_diagnostics::{ - enable_tracing_by_env, - miette::{set_panic_hook, IntoDiagnostic, Result, WrapErr}, -}; +use pacquet_diagnostics::enable_tracing_by_env; use pacquet_executor::execute_shell; use pacquet_npmrc::Npmrc; use pacquet_package_json::PackageJson; -pub async fn main() -> Result<()> { +pub async fn main() -> miette::Result<()> { enable_tracing_by_env(); set_panic_hook(); let cli = CliArgs::parse(); @@ -20,7 +18,7 @@ pub async fn main() -> Result<()> { run(cli, config).await } -async fn run(cli: CliArgs, config: &'static Npmrc) -> Result<()> { +async fn run(cli: CliArgs, config: &'static Npmrc) -> miette::Result<()> { let package_json_path = cli.dir.join("package.json"); match &cli.command { diff --git a/crates/cli/src/package_manager.rs b/crates/cli/src/package_manager.rs index 42d9b5de3..a2974a97c 100644 --- a/crates/cli/src/package_manager.rs +++ b/crates/cli/src/package_manager.rs @@ -1,7 +1,4 @@ -use pacquet_diagnostics::{ - miette::{self, Diagnostic}, - thiserror::{self, Error}, -}; +use miette::Diagnostic; use pacquet_lockfile::{LoadLockfileError, Lockfile}; use pacquet_npmrc::Npmrc; use pacquet_package_json::{PackageJson, PackageJsonError}; @@ -9,6 +6,7 @@ use pacquet_package_manager::AddError; use pacquet_tarball::Cache; use pipe_trait::Pipe; use std::path::PathBuf; +use thiserror::Error; #[derive(Error, Debug, Diagnostic)] #[non_exhaustive] From 58d12f937a72a74a88b249cc55918feb0f29ab06 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 18:19:21 +0700 Subject: [PATCH 127/210] refactor: remove unused type aliases --- crates/diagnostics/src/lib.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/crates/diagnostics/src/lib.rs b/crates/diagnostics/src/lib.rs index 7bcacdc6a..bcbfcfdf2 100644 --- a/crates/diagnostics/src/lib.rs +++ b/crates/diagnostics/src/lib.rs @@ -5,8 +5,3 @@ pub use thiserror; pub use tracing; pub use local_tracing::enable_tracing_by_env; - -pub type Error = miette::Error; -pub type Severity = miette::Severity; -pub type Report = miette::Report; -pub type Result = miette::Result; From c627b829ee6246e685026015c6bd98643541c559 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 18:19:55 +0700 Subject: [PATCH 128/210] refactor: remove re-export of macro-only crate --- crates/diagnostics/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/diagnostics/src/lib.rs b/crates/diagnostics/src/lib.rs index bcbfcfdf2..0ca66e6ce 100644 --- a/crates/diagnostics/src/lib.rs +++ b/crates/diagnostics/src/lib.rs @@ -1,7 +1,6 @@ mod local_tracing; pub use miette; -pub use thiserror; pub use tracing; pub use local_tracing::enable_tracing_by_env; From b1b0bdb0317f75a094e5901bc74e57b75237b3d0 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 18:21:40 +0700 Subject: [PATCH 129/210] refactor: use the crates directly --- Cargo.lock | 3 ++- crates/executor/Cargo.toml | 3 ++- crates/executor/src/lib.rs | 7 ++----- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5844d5bda..12b064235 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1297,7 +1297,8 @@ dependencies = [ name = "pacquet_executor" version = "0.0.1" dependencies = [ - "pacquet_diagnostics", + "miette", + "thiserror", ] [[package]] diff --git a/crates/executor/Cargo.toml b/crates/executor/Cargo.toml index 242b8102e..e491a1749 100644 --- a/crates/executor/Cargo.toml +++ b/crates/executor/Cargo.toml @@ -11,4 +11,5 @@ license.workspace = true repository.workspace = true [dependencies] -pacquet_diagnostics = { workspace = true } +miette = { workspace = true } +thiserror = { workspace = true } diff --git a/crates/executor/src/lib.rs b/crates/executor/src/lib.rs index 63fb9241f..180b6c071 100644 --- a/crates/executor/src/lib.rs +++ b/crates/executor/src/lib.rs @@ -1,9 +1,6 @@ +use miette::Diagnostic; use std::process::Command; - -use pacquet_diagnostics::{ - miette::{self, Diagnostic, Result}, - thiserror::{self, Error}, -}; +use thiserror::Error; #[derive(Error, Debug, Diagnostic)] #[non_exhaustive] From ca00e24def6bc34bf6659660f422ee23b3589952 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 18:23:27 +0700 Subject: [PATCH 130/210] refactor(executor): use derive_more --- Cargo.lock | 2 +- crates/executor/Cargo.toml | 4 ++-- crates/executor/src/lib.rs | 7 +++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 12b064235..bc7f5b9eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1297,8 +1297,8 @@ dependencies = [ name = "pacquet_executor" version = "0.0.1" dependencies = [ + "derive_more", "miette", - "thiserror", ] [[package]] diff --git a/crates/executor/Cargo.toml b/crates/executor/Cargo.toml index e491a1749..c7f82c464 100644 --- a/crates/executor/Cargo.toml +++ b/crates/executor/Cargo.toml @@ -11,5 +11,5 @@ license.workspace = true repository.workspace = true [dependencies] -miette = { workspace = true } -thiserror = { workspace = true } +derive_more = { workspace = true } +miette = { workspace = true } diff --git a/crates/executor/src/lib.rs b/crates/executor/src/lib.rs index 180b6c071..230e3dbbc 100644 --- a/crates/executor/src/lib.rs +++ b/crates/executor/src/lib.rs @@ -1,13 +1,12 @@ +use derive_more::{Display, Error, From}; use miette::Diagnostic; use std::process::Command; -use thiserror::Error; -#[derive(Error, Debug, Diagnostic)] +#[derive(Debug, Display, Error, Diagnostic, From)] #[non_exhaustive] pub enum ExecutorError { - #[error(transparent)] #[diagnostic(code(pacquet_executor::io_error))] - Io(#[from] std::io::Error), + Io(#[error(source)] std::io::Error), } pub fn execute_shell(command: &str) -> Result<(), ExecutorError> { From 35b6db484c77d33f75b17dc765529b2d5d75f8df Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 18:27:08 +0700 Subject: [PATCH 131/210] feat(executor): distinct error variants --- crates/executor/src/lib.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/crates/executor/src/lib.rs b/crates/executor/src/lib.rs index 230e3dbbc..95feb1bd8 100644 --- a/crates/executor/src/lib.rs +++ b/crates/executor/src/lib.rs @@ -1,18 +1,24 @@ -use derive_more::{Display, Error, From}; +use derive_more::{Display, Error}; use miette::Diagnostic; use std::process::Command; -#[derive(Debug, Display, Error, Diagnostic, From)] +#[derive(Debug, Display, Error, Diagnostic)] #[non_exhaustive] pub enum ExecutorError { - #[diagnostic(code(pacquet_executor::io_error))] - Io(#[error(source)] std::io::Error), + #[display(fmt = "Failed to spawn command: {_0}")] + #[diagnostic(code(pacquet_executor::spawn_command))] + SpawnCommand(#[error(source)] std::io::Error), + + #[display(fmt = "Process exits with an error: {_0}")] + #[diagnostic(code(pacquet_executor::wait_process))] + WaitProcess(#[error(source)] std::io::Error), } pub fn execute_shell(command: &str) -> Result<(), ExecutorError> { - let mut cmd = Command::new("sh").arg("-c").arg(command).spawn()?; + let mut cmd = + Command::new("sh").arg("-c").arg(command).spawn().map_err(ExecutorError::SpawnCommand)?; - cmd.wait()?; + cmd.wait().map_err(ExecutorError::WaitProcess)?; Ok(()) } From 147ff465d5498825ea9d8311a26dbc2ecb628dc7 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 18:33:39 +0700 Subject: [PATCH 132/210] fix: compile error --- Cargo.lock | 8 +++++++- crates/cli/src/bin/main.rs | 4 +--- crates/package_json/Cargo.toml | 4 ++-- crates/package_json/src/lib.rs | 6 ++---- crates/registry/Cargo.toml | 2 ++ crates/registry/src/lib.rs | 6 ++---- crates/tarball/Cargo.toml | 3 +++ crates/tarball/src/lib.rs | 8 +++----- 8 files changed, 22 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bc7f5b9eb..c7cfdc187 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1371,13 +1371,14 @@ name = "pacquet_package_json" version = "0.0.1" dependencies = [ "insta", - "pacquet_diagnostics", + "miette", "pipe-trait", "pretty_assertions", "serde", "serde_json", "strum", "tempfile", + "thiserror", ] [[package]] @@ -1413,6 +1414,7 @@ name = "pacquet_registry" version = "0.0.1" dependencies = [ "derive_more", + "miette", "node-semver", "pacquet_diagnostics", "pipe-trait", @@ -1421,6 +1423,7 @@ dependencies = [ "serde", "serde_json", "tempfile", + "thiserror", "tokio", ] @@ -1429,6 +1432,7 @@ name = "pacquet_tarball" version = "0.0.1" dependencies = [ "dashmap", + "miette", "pacquet_cafs", "pacquet_diagnostics", "pipe-trait", @@ -1437,7 +1441,9 @@ dependencies = [ "ssri", "tar", "tempfile", + "thiserror", "tokio", + "tracing", "zune-inflate", ] diff --git a/crates/cli/src/bin/main.rs b/crates/cli/src/bin/main.rs index 60210e146..33ee2777d 100644 --- a/crates/cli/src/bin/main.rs +++ b/crates/cli/src/bin/main.rs @@ -1,6 +1,4 @@ -use pacquet_diagnostics::Result; - #[tokio::main(flavor = "multi_thread")] -pub async fn main() -> Result<()> { +pub async fn main() -> miette::Result<()> { pacquet_cli::main().await } diff --git a/crates/package_json/Cargo.toml b/crates/package_json/Cargo.toml index 70186f9a4..fe8ca6c5d 100644 --- a/crates/package_json/Cargo.toml +++ b/crates/package_json/Cargo.toml @@ -11,11 +11,11 @@ license.workspace = true repository.workspace = true [dependencies] -pacquet_diagnostics = { workspace = true } - +miette = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } strum = { workspace = true } +thiserror = { workspace = true } [dev-dependencies] pipe-trait = { workspace = true } diff --git a/crates/package_json/src/lib.rs b/crates/package_json/src/lib.rs index cbd5e8eb1..03fc9acb6 100644 --- a/crates/package_json/src/lib.rs +++ b/crates/package_json/src/lib.rs @@ -4,13 +4,11 @@ use std::{ path::{Path, PathBuf}, }; -use pacquet_diagnostics::{ - miette::{self, Diagnostic}, - thiserror::{self, Error}, -}; +use miette::Diagnostic; use serde::{Deserialize, Serialize}; use serde_json::{json, Map, Value}; use strum::IntoStaticStr; +use thiserror::Error; #[derive(Error, Debug, Diagnostic)] #[non_exhaustive] diff --git a/crates/registry/Cargo.toml b/crates/registry/Cargo.toml index 3002657d3..00bbed43a 100644 --- a/crates/registry/Cargo.toml +++ b/crates/registry/Cargo.toml @@ -20,6 +20,8 @@ pipe-trait = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } tokio = { workspace = true } +miette = { workspace = true } +thiserror = { workspace = true } [dev-dependencies] pretty_assertions = { workspace = true } diff --git a/crates/registry/src/lib.rs b/crates/registry/src/lib.rs index e86ee5d8c..30c4aa2f9 100644 --- a/crates/registry/src/lib.rs +++ b/crates/registry/src/lib.rs @@ -8,10 +8,8 @@ pub use package_distribution::PackageDistribution; pub use package_tag::PackageTag; pub use package_version::PackageVersion; -use pacquet_diagnostics::{ - miette::{self, Diagnostic}, - thiserror::{self, Error}, -}; +use miette::Diagnostic; +use thiserror::Error; #[derive(Debug, Error)] #[error("failed to request {url}: {error}")] diff --git a/crates/tarball/Cargo.toml b/crates/tarball/Cargo.toml index b273503af..5232d3c1d 100644 --- a/crates/tarball/Cargo.toml +++ b/crates/tarball/Cargo.toml @@ -15,12 +15,15 @@ pacquet_cafs = { workspace = true } pacquet_diagnostics = { workspace = true } dashmap = { workspace = true } +miette = { workspace = true } pipe-trait = { workspace = true } reqwest = { workspace = true } ssri = { workspace = true } tar = { workspace = true } tokio = { workspace = true } zune-inflate = { workspace = true } +thiserror = { workspace = true } +tracing = { workspace = true } [dev-dependencies] pretty_assertions = { workspace = true } diff --git a/crates/tarball/src/lib.rs b/crates/tarball/src/lib.rs index f33783f95..a6feeac45 100644 --- a/crates/tarball/src/lib.rs +++ b/crates/tarball/src/lib.rs @@ -7,16 +7,14 @@ use std::{ }; use dashmap::DashMap; -use pacquet_diagnostics::{ - miette::{self, Diagnostic}, - thiserror::{self, Error}, - tracing::{self, instrument}, -}; +use miette::Diagnostic; use pipe_trait::Pipe; use reqwest::Client; use ssri::{Integrity, IntegrityChecker}; use tar::Archive; +use thiserror::Error; use tokio::sync::{Notify, RwLock}; +use tracing::instrument; use zune_inflate::{errors::InflateDecodeErrors, DeflateDecoder, DeflateOptions}; #[derive(Error, Debug, Diagnostic)] From a9206da4420f63b04a887283a6f8ff5fbbf93bba Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 21:19:49 +0700 Subject: [PATCH 133/210] refactor(test): proper integration test --- Cargo.lock | 72 +++++++++++++++++++ Cargo.toml | 1 + crates/cli/Cargo.toml | 1 + crates/cli/src/cli_command/add.rs | 44 +----------- crates/cli/tests/add.rs | 37 ++++++++++ ...add__should_install_all_dependencies.snap} | 4 +- 6 files changed, 114 insertions(+), 45 deletions(-) create mode 100644 crates/cli/tests/add.rs rename crates/cli/{src/cli_command/snapshots/pacquet_cli__cli_command__add__tests__should_install_all_dependencies.snap => tests/snapshots/add__should_install_all_dependencies.snap} (95%) diff --git a/Cargo.lock b/Cargo.lock index c7cfdc187..9dc9502e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -90,6 +90,21 @@ dependencies = [ "serde_json", ] +[[package]] +name = "assert_cmd" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88903cb14723e4d4003335bb7f8a14f27691649105346a0f0957466c096adfe6" +dependencies = [ + "anstyle", + "bstr", + "doc-comment", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + [[package]] name = "async-recursion" version = "1.0.5" @@ -165,6 +180,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" dependencies = [ "memchr", + "regex-automata 0.3.4", "serde", ] @@ -444,6 +460,12 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + [[package]] name = "digest" version = "0.10.7" @@ -454,6 +476,12 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + [[package]] name = "either" version = "1.9.0" @@ -1260,6 +1288,7 @@ dependencies = [ name = "pacquet_cli" version = "0.0.1" dependencies = [ + "assert_cmd", "clap", "insta", "miette", @@ -1542,6 +1571,34 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "predicates" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dfc28575c2e3f19cb3c73b93af36460ae898d426eba6fc15b9bd2a5220758a0" +dependencies = [ + "anstyle", + "difflib", + "itertools 0.11.0", + "predicates-core", +] + +[[package]] +name = "predicates-core" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" + +[[package]] +name = "predicates-tree" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +dependencies = [ + "predicates-core", + "termtree", +] + [[package]] name = "pretty_assertions" version = "1.4.0" @@ -2121,6 +2178,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "termtree" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" + [[package]] name = "text-block-macros" version = "0.1.1" @@ -2408,6 +2471,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "walkdir" version = "2.4.0" diff --git a/Cargo.toml b/Cargo.toml index 8cd4ca14b..d6a807dd6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,6 +62,7 @@ zune-inflate = { version = "0.2.54" } # Dev dependencies +assert_cmd = { version = "2.0.12" } criterion = { version = "0.5.1", features = ["async_tokio"] } pretty_assertions = { version = "1.4.0" } project-root = { version = "0.2.2" } diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 9f935795c..4884497c8 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -37,6 +37,7 @@ tracing = { workspace = true } [dev-dependencies] pacquet_testing_utils = { workspace = true } +assert_cmd = { workspace = true } insta = { workspace = true } pretty_assertions = { workspace = true } tempfile = { workspace = true } diff --git a/crates/cli/src/cli_command/add.rs b/crates/cli/src/cli_command/add.rs index 4d73f8961..b86104f55 100644 --- a/crates/cli/src/cli_command/add.rs +++ b/crates/cli/src/cli_command/add.rs @@ -78,7 +78,7 @@ mod tests { use super::*; use pacquet_npmrc::Npmrc; use pacquet_package_json::{DependencyGroup, PackageJson}; - use pacquet_testing_utils::fs::{get_all_folders, get_filenames_in_folder}; + use pacquet_testing_utils::fs::get_all_folders; use pretty_assertions::assert_eq; use std::{env, fs}; use tempfile::tempdir; @@ -177,48 +177,6 @@ mod tests { ); } - #[tokio::test] - pub async fn should_install_all_dependencies() { - let dir = tempdir().unwrap(); - let virtual_store_dir = dir.path().join("node_modules/.pacquet"); - let current_directory = env::current_dir().unwrap(); - env::set_current_dir(&dir).unwrap(); - let package_json = dir.path().join("package.json"); - let mut manager = PackageManager::new(&package_json, Npmrc::current().leak()).unwrap(); - - // It should create a package_json if not exist - assert!(package_json.exists()); - - let args = AddArgs { - package: "is-even".to_string(), - dependency_options: AddDependencyOptions { - save_prod: false, - save_dev: false, - save_peer: false, - save_optional: false, - }, - save_exact: false, - virtual_store_dir: virtual_store_dir.to_string_lossy().to_string(), - }; - manager.add(&args).await.unwrap(); - - insta::assert_debug_snapshot!(get_all_folders(dir.path())); - - // Ensure that is-buffer does not have any dependencies - let is_buffer_path = virtual_store_dir.join("is-buffer@1.1.6/node_modules"); - assert_eq!(get_filenames_in_folder(&is_buffer_path), vec!["is-buffer"]); - - // Ensure that is-even have correct dependencies - let is_even_path = virtual_store_dir.join("is-even@1.0.0/node_modules"); - assert_eq!(get_filenames_in_folder(&is_even_path), vec!["is-even", "is-odd"]); - - // Ensure that is-number does not have any dependencies - let is_number_path = virtual_store_dir.join("is-number@3.0.0/node_modules"); - assert_eq!(get_filenames_in_folder(&is_number_path), vec!["is-number", "kind-of"]); - - env::set_current_dir(¤t_directory).unwrap(); - } - #[tokio::test] #[cfg(not(target_os = "windows"))] pub async fn should_symlink_correctly() { diff --git a/crates/cli/tests/add.rs b/crates/cli/tests/add.rs new file mode 100644 index 000000000..a49a190ae --- /dev/null +++ b/crates/cli/tests/add.rs @@ -0,0 +1,37 @@ +use assert_cmd::prelude::*; +use pacquet_testing_utils::fs::{get_all_folders, get_filenames_in_folder}; +use pretty_assertions::assert_eq; +use std::{env, process::Command}; +use tempfile::tempdir; + +#[test] +fn should_install_all_dependencies() { + let dir = tempdir().unwrap(); + Command::cargo_bin("pacquet") + .expect("find pacquet binary") + .current_dir(dir.path()) + .arg("add") + .arg("is-even") + .assert() + .success(); + + eprintln!("Snapshot"); + insta::assert_debug_snapshot!(get_all_folders(dir.path())); + + let virtual_store_dir = dir.path().join("node_modules").join(".pacquet"); + + eprintln!("Ensure virtual store dir ({virtual_store_dir:?}) exists"); + assert!(virtual_store_dir.exists()); + + eprintln!("Ensure that is-buffer does not have any dependencies"); + let is_buffer_path = virtual_store_dir.join("is-buffer@1.1.6/node_modules"); + assert_eq!(get_filenames_in_folder(&is_buffer_path), vec!["is-buffer"]); + + eprintln!("Ensure that is-even have correct dependencies"); + let is_even_path = virtual_store_dir.join("is-even@1.0.0/node_modules"); + assert_eq!(get_filenames_in_folder(&is_even_path), vec!["is-even", "is-odd"]); + + eprintln!("Ensure that is-number does not have any dependencies"); + let is_number_path = virtual_store_dir.join("is-number@3.0.0/node_modules"); + assert_eq!(get_filenames_in_folder(&is_number_path), vec!["is-number", "kind-of"]); +} diff --git a/crates/cli/src/cli_command/snapshots/pacquet_cli__cli_command__add__tests__should_install_all_dependencies.snap b/crates/cli/tests/snapshots/add__should_install_all_dependencies.snap similarity index 95% rename from crates/cli/src/cli_command/snapshots/pacquet_cli__cli_command__add__tests__should_install_all_dependencies.snap rename to crates/cli/tests/snapshots/add__should_install_all_dependencies.snap index 5220135c3..0591e544f 100644 --- a/crates/cli/src/cli_command/snapshots/pacquet_cli__cli_command__add__tests__should_install_all_dependencies.snap +++ b/crates/cli/tests/snapshots/add__should_install_all_dependencies.snap @@ -1,6 +1,6 @@ --- -source: crates/cli/src/cli_command/add.rs -assertion_line: 126 +source: crates/cli/tests/add.rs +assertion_line: 19 expression: get_all_folders(dir.path()) --- [ From 24e4a8e48d217bb8a49ad0be7db65a68f0285ca5 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 21:25:10 +0700 Subject: [PATCH 134/210] test(cli): package.json --- crates/cli/tests/add.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/cli/tests/add.rs b/crates/cli/tests/add.rs index a49a190ae..ba3fc5904 100644 --- a/crates/cli/tests/add.rs +++ b/crates/cli/tests/add.rs @@ -18,6 +18,11 @@ fn should_install_all_dependencies() { eprintln!("Snapshot"); insta::assert_debug_snapshot!(get_all_folders(dir.path())); + let package_json_path = dir.path().join("package.json"); + + eprintln!("Ensure the manifest file ({package_json_path:?}) exists"); + assert!(package_json_path.exists()); + let virtual_store_dir = dir.path().join("node_modules").join(".pacquet"); eprintln!("Ensure virtual store dir ({virtual_store_dir:?}) exists"); From 3a5c86d78bf5cce3b08d9fbf99dbab259e893f8c Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 21:30:16 +0700 Subject: [PATCH 135/210] test(cli): proper integration test --- crates/cli/src/cli_command/add.rs | 37 +------------------ crates/cli/tests/add.rs | 34 ++++++++++++++++- .../add__should_symlink_correctly.snap} | 4 +- 3 files changed, 36 insertions(+), 39 deletions(-) rename crates/cli/{src/cli_command/snapshots/pacquet_cli__cli_command__add__tests__should_symlink_correctly.snap => tests/snapshots/add__should_symlink_correctly.snap} (89%) diff --git a/crates/cli/src/cli_command/add.rs b/crates/cli/src/cli_command/add.rs index b86104f55..65266e351 100644 --- a/crates/cli/src/cli_command/add.rs +++ b/crates/cli/src/cli_command/add.rs @@ -78,9 +78,8 @@ mod tests { use super::*; use pacquet_npmrc::Npmrc; use pacquet_package_json::{DependencyGroup, PackageJson}; - use pacquet_testing_utils::fs::get_all_folders; use pretty_assertions::assert_eq; - use std::{env, fs}; + use std::env; use tempfile::tempdir; #[test] @@ -177,40 +176,6 @@ mod tests { ); } - #[tokio::test] - #[cfg(not(target_os = "windows"))] - pub async fn should_symlink_correctly() { - let dir = tempdir().unwrap(); - let virtual_store_dir = dir.path().join("node_modules/.pacquet"); - let current_directory = env::current_dir().unwrap(); - env::set_current_dir(&dir).unwrap(); - let package_json = dir.path().join("package.json"); - let mut manager = PackageManager::new(&package_json, Npmrc::current().leak()).unwrap(); - - let args = AddArgs { - package: "is-odd".to_string(), - dependency_options: AddDependencyOptions { - save_prod: false, - save_dev: false, - save_peer: false, - save_optional: false, - }, - save_exact: false, - virtual_store_dir: virtual_store_dir.to_string_lossy().to_string(), - }; - manager.add(&args).await.unwrap(); - - insta::assert_debug_snapshot!(get_all_folders(dir.path())); - - // Make sure the symlinks are correct - assert_eq!( - fs::read_link(virtual_store_dir.join("is-odd@3.0.1/node_modules/is-number")).unwrap(), - fs::canonicalize(virtual_store_dir.join("is-number@6.0.0/node_modules/is-number")) - .unwrap(), - ); - env::set_current_dir(¤t_directory).unwrap(); - } - #[tokio::test] async fn should_add_to_package_json() { let dir = tempdir().unwrap(); diff --git a/crates/cli/tests/add.rs b/crates/cli/tests/add.rs index ba3fc5904..1d917b942 100644 --- a/crates/cli/tests/add.rs +++ b/crates/cli/tests/add.rs @@ -1,7 +1,7 @@ use assert_cmd::prelude::*; use pacquet_testing_utils::fs::{get_all_folders, get_filenames_in_folder}; use pretty_assertions::assert_eq; -use std::{env, process::Command}; +use std::{env, fs, process::Command}; use tempfile::tempdir; #[test] @@ -40,3 +40,35 @@ fn should_install_all_dependencies() { let is_number_path = virtual_store_dir.join("is-number@3.0.0/node_modules"); assert_eq!(get_filenames_in_folder(&is_number_path), vec!["is-number", "kind-of"]); } + +#[test] +#[cfg(unix)] +pub fn should_symlink_correctly() { + let dir = tempdir().unwrap(); + Command::cargo_bin("pacquet") + .expect("find pacquet binary") + .current_dir(dir.path()) + .arg("add") + .arg("is-odd") + .assert() + .success(); + + eprintln!("Snapshot"); + insta::assert_debug_snapshot!(get_all_folders(dir.path())); + + let package_json_path = dir.path().join("package.json"); + + eprintln!("Ensure the manifest file ({package_json_path:?}) exists"); + assert!(package_json_path.exists()); + + let virtual_store_dir = dir.path().join("node_modules").join(".pacquet"); + + eprintln!("Ensure virtual store dir ({virtual_store_dir:?}) exists"); + assert!(virtual_store_dir.exists()); + + // Make sure the symlinks are correct + assert_eq!( + fs::read_link(virtual_store_dir.join("is-odd@3.0.1/node_modules/is-number")).unwrap(), + fs::canonicalize(virtual_store_dir.join("is-number@6.0.0/node_modules/is-number")).unwrap(), + ); +} diff --git a/crates/cli/src/cli_command/snapshots/pacquet_cli__cli_command__add__tests__should_symlink_correctly.snap b/crates/cli/tests/snapshots/add__should_symlink_correctly.snap similarity index 89% rename from crates/cli/src/cli_command/snapshots/pacquet_cli__cli_command__add__tests__should_symlink_correctly.snap rename to crates/cli/tests/snapshots/add__should_symlink_correctly.snap index 3709a5a7e..04f3d30f4 100644 --- a/crates/cli/src/cli_command/snapshots/pacquet_cli__cli_command__add__tests__should_symlink_correctly.snap +++ b/crates/cli/tests/snapshots/add__should_symlink_correctly.snap @@ -1,6 +1,6 @@ --- -source: crates/cli/src/cli_command/add.rs -assertion_line: 164 +source: crates/cli/tests/add.rs +assertion_line: 57 expression: get_all_folders(dir.path()) --- [ From ba579188cc742fce56828f1e8d81103e4913cf9b Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 21:30:56 +0700 Subject: [PATCH 136/210] test(cli): change titles --- crates/cli/tests/add.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/cli/tests/add.rs b/crates/cli/tests/add.rs index 1d917b942..99e2cb31f 100644 --- a/crates/cli/tests/add.rs +++ b/crates/cli/tests/add.rs @@ -15,7 +15,7 @@ fn should_install_all_dependencies() { .assert() .success(); - eprintln!("Snapshot"); + eprintln!("Directory list"); insta::assert_debug_snapshot!(get_all_folders(dir.path())); let package_json_path = dir.path().join("package.json"); @@ -53,7 +53,7 @@ pub fn should_symlink_correctly() { .assert() .success(); - eprintln!("Snapshot"); + eprintln!("Directory list"); insta::assert_debug_snapshot!(get_all_folders(dir.path())); let package_json_path = dir.path().join("package.json"); From 90089795cabdd6399ea15f27fca787aec89629bf Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 21:32:06 +0700 Subject: [PATCH 137/210] test(cli): add missing title --- crates/cli/tests/add.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli/tests/add.rs b/crates/cli/tests/add.rs index 99e2cb31f..46b6bf5ac 100644 --- a/crates/cli/tests/add.rs +++ b/crates/cli/tests/add.rs @@ -66,7 +66,7 @@ pub fn should_symlink_correctly() { eprintln!("Ensure virtual store dir ({virtual_store_dir:?}) exists"); assert!(virtual_store_dir.exists()); - // Make sure the symlinks are correct + eprintln!("Make sure the symlinks are correct"); assert_eq!( fs::read_link(virtual_store_dir.join("is-odd@3.0.1/node_modules/is-number")).unwrap(), fs::canonicalize(virtual_store_dir.join("is-number@6.0.0/node_modules/is-number")).unwrap(), From caeabd22a8333fb6938b61d195e77d2d8297b6ec Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 21:50:13 +0700 Subject: [PATCH 138/210] refactor(test): reuse code --- Cargo.lock | 2 ++ crates/cli/package.json | 15 +++++++++++++ crates/cli/tests/add.rs | 37 ++++++++++++++++----------------- crates/testing-utils/Cargo.toml | 4 +++- crates/testing-utils/src/bin.rs | 9 ++++++++ crates/testing-utils/src/lib.rs | 1 + 6 files changed, 48 insertions(+), 20 deletions(-) create mode 100644 crates/cli/package.json create mode 100644 crates/testing-utils/src/bin.rs diff --git a/Cargo.lock b/Cargo.lock index 9dc9502e5..eb276fd0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1480,7 +1480,9 @@ dependencies = [ name = "pacquet_testing_utils" version = "0.0.0" dependencies = [ + "assert_cmd", "junction", + "tempfile", "walkdir", ] diff --git a/crates/cli/package.json b/crates/cli/package.json new file mode 100644 index 000000000..42164e7af --- /dev/null +++ b/crates/cli/package.json @@ -0,0 +1,15 @@ +{ + "name": "", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "is-even": "^1.0.0" + } +} \ No newline at end of file diff --git a/crates/cli/tests/add.rs b/crates/cli/tests/add.rs index 46b6bf5ac..b15614a2d 100644 --- a/crates/cli/tests/add.rs +++ b/crates/cli/tests/add.rs @@ -1,19 +1,25 @@ use assert_cmd::prelude::*; -use pacquet_testing_utils::fs::{get_all_folders, get_filenames_in_folder}; +use pacquet_testing_utils::{ + bin::pacquet_with_temp_cwd, + fs::{get_all_folders, get_filenames_in_folder}, +}; use pretty_assertions::assert_eq; -use std::{env, fs, process::Command}; -use tempfile::tempdir; +use std::{env, ffi::OsStr, fs}; +use tempfile::TempDir; + +pub fn exec_pacquet_in_temp_cwd(args: Args) -> TempDir +where + Args: IntoIterator, + Args::Item: AsRef, +{ + let (mut command, current_dir) = pacquet_with_temp_cwd(); + command.current_dir(current_dir.path()).args(args).assert().success(); + current_dir +} #[test] fn should_install_all_dependencies() { - let dir = tempdir().unwrap(); - Command::cargo_bin("pacquet") - .expect("find pacquet binary") - .current_dir(dir.path()) - .arg("add") - .arg("is-even") - .assert() - .success(); + let dir = exec_pacquet_in_temp_cwd(["add", "is-even"]); eprintln!("Directory list"); insta::assert_debug_snapshot!(get_all_folders(dir.path())); @@ -44,14 +50,7 @@ fn should_install_all_dependencies() { #[test] #[cfg(unix)] pub fn should_symlink_correctly() { - let dir = tempdir().unwrap(); - Command::cargo_bin("pacquet") - .expect("find pacquet binary") - .current_dir(dir.path()) - .arg("add") - .arg("is-odd") - .assert() - .success(); + let dir = exec_pacquet_in_temp_cwd(["add", "is-odd"]); eprintln!("Directory list"); insta::assert_debug_snapshot!(get_all_folders(dir.path())); diff --git a/crates/testing-utils/Cargo.toml b/crates/testing-utils/Cargo.toml index e443a60a4..d9e361c47 100644 --- a/crates/testing-utils/Cargo.toml +++ b/crates/testing-utils/Cargo.toml @@ -11,7 +11,9 @@ license.workspace = true repository.workspace = true [dependencies] -walkdir = { workspace = true } +assert_cmd = { workspace = true } +tempfile = { workspace = true } +walkdir = { workspace = true } [target.'cfg(windows)'.dependencies] junction = { workspace = true } diff --git a/crates/testing-utils/src/bin.rs b/crates/testing-utils/src/bin.rs new file mode 100644 index 000000000..b0570c89f --- /dev/null +++ b/crates/testing-utils/src/bin.rs @@ -0,0 +1,9 @@ +use assert_cmd::prelude::*; +use std::process::Command; +use tempfile::{tempdir, TempDir}; + +pub fn pacquet_with_temp_cwd() -> (Command, TempDir) { + let current_dir = tempdir().expect("create temporary working directory for pacquet"); + let command = Command::cargo_bin("pacquet").expect("find the pacquet binary"); + (command, current_dir) +} diff --git a/crates/testing-utils/src/lib.rs b/crates/testing-utils/src/lib.rs index d521fbd77..36ebebf8e 100644 --- a/crates/testing-utils/src/lib.rs +++ b/crates/testing-utils/src/lib.rs @@ -1 +1,2 @@ +pub mod bin; pub mod fs; From c63546865f0439a5f41f19b8aabc231008cfd5b1 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 21:54:59 +0700 Subject: [PATCH 139/210] test(cli): proper integration test --- crates/cli/src/cli_command/add.rs | 26 -------------------------- crates/cli/tests/add.rs | 8 ++++++++ 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/crates/cli/src/cli_command/add.rs b/crates/cli/src/cli_command/add.rs index 65266e351..aeb87457b 100644 --- a/crates/cli/src/cli_command/add.rs +++ b/crates/cli/src/cli_command/add.rs @@ -176,32 +176,6 @@ mod tests { ); } - #[tokio::test] - async fn should_add_to_package_json() { - let dir = tempdir().unwrap(); - let virtual_store_dir = dir.path().join("node_modules/.pacquet"); - let current_directory = env::current_dir().unwrap(); - env::set_current_dir(&dir).unwrap(); - let package_json = dir.path().join("package.json"); - let mut manager = PackageManager::new(&package_json, Npmrc::current().leak()).unwrap(); - - let args = AddArgs { - package: "is-odd".to_string(), - dependency_options: AddDependencyOptions { - save_prod: false, - save_dev: false, - save_peer: false, - save_optional: false, - }, - save_exact: false, - virtual_store_dir: virtual_store_dir.to_string_lossy().to_string(), - }; - manager.add(&args).await.unwrap(); - let file = PackageJson::from_path(dir.path().join("package.json")).unwrap(); - assert!(file.dependencies([DependencyGroup::Default]).any(|(k, _)| k == "is-odd")); - env::set_current_dir(¤t_directory).unwrap(); - } - #[tokio::test] async fn should_add_dev_dependency() { let dir = tempdir().unwrap(); diff --git a/crates/cli/tests/add.rs b/crates/cli/tests/add.rs index b15614a2d..b13c973fa 100644 --- a/crates/cli/tests/add.rs +++ b/crates/cli/tests/add.rs @@ -1,4 +1,5 @@ use assert_cmd::prelude::*; +use pacquet_package_json::{DependencyGroup, PackageJson}; use pacquet_testing_utils::{ bin::pacquet_with_temp_cwd, fs::{get_all_folders, get_filenames_in_folder}, @@ -71,3 +72,10 @@ pub fn should_symlink_correctly() { fs::canonicalize(virtual_store_dir.join("is-number@6.0.0/node_modules/is-number")).unwrap(), ); } + +#[test] +fn should_add_to_package_json() { + let dir = exec_pacquet_in_temp_cwd(["add", "is-odd"]); + let file = PackageJson::from_path(dir.path().join("package.json")).unwrap(); + assert!(file.dependencies([DependencyGroup::Default]).any(|(k, _)| k == "is-odd")); +} From ab25256e504780e0d5e02cfbd9b7247f9423f433 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 22:06:06 +0700 Subject: [PATCH 140/210] test(cli): add a title --- crates/cli/tests/add.rs | 1 + crates/package_json/src/lib.rs | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/crates/cli/tests/add.rs b/crates/cli/tests/add.rs index b13c973fa..b029406de 100644 --- a/crates/cli/tests/add.rs +++ b/crates/cli/tests/add.rs @@ -77,5 +77,6 @@ pub fn should_symlink_correctly() { fn should_add_to_package_json() { let dir = exec_pacquet_in_temp_cwd(["add", "is-odd"]); let file = PackageJson::from_path(dir.path().join("package.json")).unwrap(); + eprintln!("Ensure is-odd is added to package.json"); assert!(file.dependencies([DependencyGroup::Default]).any(|(k, _)| k == "is-odd")); } diff --git a/crates/package_json/src/lib.rs b/crates/package_json/src/lib.rs index 03fc9acb6..bfa041cee 100644 --- a/crates/package_json/src/lib.rs +++ b/crates/package_json/src/lib.rs @@ -126,6 +126,10 @@ impl PackageJson { Ok(PackageJson { path, value }) } + pub fn value(&self) -> &Value { + &self.value + } + pub fn save(&self) -> Result<(), PackageJsonError> { let mut file = fs::File::create(&self.path)?; let contents = serde_json::to_string_pretty(&self.value)?; From 447b89925c3453687c2588671a587312afab91cd Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 22:20:46 +0700 Subject: [PATCH 141/210] test(cli): integration test for `pacquet install` --- Cargo.lock | 1 + crates/cli/Cargo.toml | 1 + crates/cli/tests/install.rs | 43 +++++++++++++++++++ .../install__should_install_dependencies.snap | 21 +++++++++ 4 files changed, 66 insertions(+) create mode 100644 crates/cli/tests/install.rs create mode 100644 crates/cli/tests/snapshots/install__should_install_dependencies.snap diff --git a/Cargo.lock b/Cargo.lock index eb276fd0e..41199df6e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1306,6 +1306,7 @@ dependencies = [ "pipe-trait", "pretty_assertions", "reqwest", + "serde_json", "tempfile", "thiserror", "tokio", diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 4884497c8..33728f2bb 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -40,4 +40,5 @@ pacquet_testing_utils = { workspace = true } assert_cmd = { workspace = true } insta = { workspace = true } pretty_assertions = { workspace = true } +serde_json = { workspace = true } tempfile = { workspace = true } diff --git a/crates/cli/tests/install.rs b/crates/cli/tests/install.rs new file mode 100644 index 000000000..f334ee875 --- /dev/null +++ b/crates/cli/tests/install.rs @@ -0,0 +1,43 @@ +use assert_cmd::prelude::*; +use pacquet_testing_utils::{ + bin::pacquet_with_temp_cwd, + fs::{get_all_folders, is_symlink_or_junction}, +}; +use std::fs; + +#[test] +fn should_install_dependencies() { + let (mut command, dir) = pacquet_with_temp_cwd(); + + eprintln!("Creating package.json..."); + let package_json_path = dir.path().join("package.json"); + let package_json_content = serde_json::json!({ + "dependencies": { + "is-odd": "3.0.1", + }, + "devDependencies": { + "fast-decode-uri-component": "1.0.1", + }, + }); + fs::write(&package_json_path, package_json_content.to_string()).expect("write to package.json"); + + eprintln!("Executing command..."); + command.current_dir(dir.path()).arg("install").assert().success(); + + eprintln!("Make sure the package is installed"); + assert!(is_symlink_or_junction(&dir.path().join("node_modules/is-odd")).unwrap()); + assert!(dir.path().join("node_modules/.pacquet/is-odd@3.0.1").exists()); + + eprintln!("Make sure it installs direct dependencies"); + assert!(!dir.path().join("node_modules/is-number").exists()); + assert!(dir.path().join("node_modules/.pacquet/is-number@6.0.0").exists()); + + eprintln!("Make sure we install dev-dependencies as well"); + assert!( + is_symlink_or_junction(&dir.path().join("node_modules/fast-decode-uri-component")).unwrap() + ); + assert!(dir.path().join("node_modules/.pacquet/fast-decode-uri-component@1.0.1").is_dir()); + + eprintln!("Directory list"); + insta::assert_debug_snapshot!(get_all_folders(dir.path())); +} diff --git a/crates/cli/tests/snapshots/install__should_install_dependencies.snap b/crates/cli/tests/snapshots/install__should_install_dependencies.snap new file mode 100644 index 000000000..a059e4940 --- /dev/null +++ b/crates/cli/tests/snapshots/install__should_install_dependencies.snap @@ -0,0 +1,21 @@ +--- +source: crates/cli/tests/install.rs +assertion_line: 74 +expression: get_all_folders(dir.path()) +--- +[ + "node_modules", + "node_modules/.pacquet", + "node_modules/.pacquet/fast-decode-uri-component@1.0.1", + "node_modules/.pacquet/fast-decode-uri-component@1.0.1/node_modules", + "node_modules/.pacquet/fast-decode-uri-component@1.0.1/node_modules/fast-decode-uri-component", + "node_modules/.pacquet/is-number@6.0.0", + "node_modules/.pacquet/is-number@6.0.0/node_modules", + "node_modules/.pacquet/is-number@6.0.0/node_modules/is-number", + "node_modules/.pacquet/is-odd@3.0.1", + "node_modules/.pacquet/is-odd@3.0.1/node_modules", + "node_modules/.pacquet/is-odd@3.0.1/node_modules/is-number", + "node_modules/.pacquet/is-odd@3.0.1/node_modules/is-odd", + "node_modules/fast-decode-uri-component", + "node_modules/is-odd", +] From 1769c60cf1905c80e0b3bdb2fae2983f2ba516cd Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 22:23:19 +0700 Subject: [PATCH 142/210] test(cli): change title --- crates/cli/tests/add.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli/tests/add.rs b/crates/cli/tests/add.rs index b029406de..c2d76ecfb 100644 --- a/crates/cli/tests/add.rs +++ b/crates/cli/tests/add.rs @@ -77,6 +77,6 @@ pub fn should_symlink_correctly() { fn should_add_to_package_json() { let dir = exec_pacquet_in_temp_cwd(["add", "is-odd"]); let file = PackageJson::from_path(dir.path().join("package.json")).unwrap(); - eprintln!("Ensure is-odd is added to package.json"); + eprintln!("Ensure is-odd is added to package.json#dependencies"); assert!(file.dependencies([DependencyGroup::Default]).any(|(k, _)| k == "is-odd")); } From db05100f9875d291255fba0f14d6767b8871306c Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 22:25:17 +0700 Subject: [PATCH 143/210] test(cli): proper integration test --- crates/cli/src/cli_command/add.rs | 26 -------------------------- crates/cli/tests/add.rs | 8 ++++++++ 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/crates/cli/src/cli_command/add.rs b/crates/cli/src/cli_command/add.rs index aeb87457b..409cd9db3 100644 --- a/crates/cli/src/cli_command/add.rs +++ b/crates/cli/src/cli_command/add.rs @@ -176,32 +176,6 @@ mod tests { ); } - #[tokio::test] - async fn should_add_dev_dependency() { - let dir = tempdir().unwrap(); - let virtual_store_dir = dir.path().join("node_modules/.pacquet"); - let current_directory = env::current_dir().unwrap(); - env::set_current_dir(&dir).unwrap(); - let package_json = dir.path().join("package.json"); - let mut manager = PackageManager::new(&package_json, Npmrc::current().leak()).unwrap(); - - let args = AddArgs { - package: "is-odd".to_string(), - dependency_options: AddDependencyOptions { - save_prod: false, - save_dev: true, - save_peer: false, - save_optional: false, - }, - save_exact: false, - virtual_store_dir: virtual_store_dir.to_string_lossy().to_string(), - }; - manager.add(&args).await.unwrap(); - let file = PackageJson::from_path(dir.path().join("package.json")).unwrap(); - assert!(file.dependencies([DependencyGroup::Dev]).any(|(k, _)| k == "is-odd")); - env::set_current_dir(¤t_directory).unwrap(); - } - #[tokio::test] async fn should_add_peer_dependency() { let dir = tempdir().unwrap(); diff --git a/crates/cli/tests/add.rs b/crates/cli/tests/add.rs index c2d76ecfb..83e93a20f 100644 --- a/crates/cli/tests/add.rs +++ b/crates/cli/tests/add.rs @@ -80,3 +80,11 @@ fn should_add_to_package_json() { eprintln!("Ensure is-odd is added to package.json#dependencies"); assert!(file.dependencies([DependencyGroup::Default]).any(|(k, _)| k == "is-odd")); } + +#[test] +fn should_add_dev_dependency() { + let dir = exec_pacquet_in_temp_cwd(["add", "is-odd", "--save-dev"]); + let file = PackageJson::from_path(dir.path().join("package.json")).unwrap(); + eprintln!("Ensure is-odd is added to package.json#devDependencies"); + assert!(file.dependencies([DependencyGroup::Dev]).any(|(k, _)| k == "is-odd")); +} From 1f7fdcc7ad4176233f0d695e37d43ad11bf16682 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sat, 14 Oct 2023 22:28:43 +0700 Subject: [PATCH 144/210] test(cli): proper integration test --- crates/cli/src/cli_command/add.rs | 32 +------------------------------ crates/cli/tests/add.rs | 10 ++++++++++ 2 files changed, 11 insertions(+), 31 deletions(-) diff --git a/crates/cli/src/cli_command/add.rs b/crates/cli/src/cli_command/add.rs index 409cd9db3..ab3c9f370 100644 --- a/crates/cli/src/cli_command/add.rs +++ b/crates/cli/src/cli_command/add.rs @@ -76,11 +76,8 @@ impl PackageManager { #[cfg(test)] mod tests { use super::*; - use pacquet_npmrc::Npmrc; - use pacquet_package_json::{DependencyGroup, PackageJson}; + use pacquet_package_json::DependencyGroup; use pretty_assertions::assert_eq; - use std::env; - use tempfile::tempdir; #[test] fn dependency_options_to_dependency_groups() { @@ -175,31 +172,4 @@ mod tests { [Optional, Peer] ); } - - #[tokio::test] - async fn should_add_peer_dependency() { - let dir = tempdir().unwrap(); - let virtual_store_dir = dir.path().join("node_modules/.pacquet"); - let current_directory = env::current_dir().unwrap(); - env::set_current_dir(&dir).unwrap(); - let package_json = dir.path().join("package.json"); - let mut manager = PackageManager::new(&package_json, Npmrc::current().leak()).unwrap(); - - let args = AddArgs { - package: "is-odd".to_string(), - dependency_options: AddDependencyOptions { - save_prod: false, - save_dev: false, - save_peer: true, - save_optional: false, - }, - save_exact: false, - virtual_store_dir: virtual_store_dir.to_string_lossy().to_string(), - }; - manager.add(&args).await.unwrap(); - let file = PackageJson::from_path(dir.path().join("package.json")).unwrap(); - assert!(file.dependencies([DependencyGroup::Dev]).any(|(k, _)| k == "is-odd")); - assert!(file.dependencies([DependencyGroup::Peer]).any(|(k, _)| k == "is-odd")); - env::set_current_dir(¤t_directory).unwrap(); - } } diff --git a/crates/cli/tests/add.rs b/crates/cli/tests/add.rs index 83e93a20f..08b657623 100644 --- a/crates/cli/tests/add.rs +++ b/crates/cli/tests/add.rs @@ -88,3 +88,13 @@ fn should_add_dev_dependency() { eprintln!("Ensure is-odd is added to package.json#devDependencies"); assert!(file.dependencies([DependencyGroup::Dev]).any(|(k, _)| k == "is-odd")); } + +#[test] +fn should_add_peer_dependency() { + let dir = exec_pacquet_in_temp_cwd(["add", "is-odd", "--save-peer"]); + let file = PackageJson::from_path(dir.path().join("package.json")).unwrap(); + eprintln!("Ensure is-odd is added to package.json#devDependencies"); + assert!(file.dependencies([DependencyGroup::Dev]).any(|(k, _)| k == "is-odd")); + eprintln!("Ensure is-odd is added to package.json#peerDependencies"); + assert!(file.dependencies([DependencyGroup::Peer]).any(|(k, _)| k == "is-odd")); +} From 98ba757f4c86605167cb07f43e8e4b837a1665b1 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 00:02:28 +0700 Subject: [PATCH 145/210] refactor(cli): rename `cli_command` to `cli_args` --- crates/cli/src/{cli_command.rs => cli_args.rs} | 0 crates/cli/src/{cli_command => cli_args}/add.rs | 0 crates/cli/src/{cli_command => cli_args}/install.rs | 0 crates/cli/src/{cli_command => cli_args}/run.rs | 0 crates/cli/src/{cli_command => cli_args}/store.rs | 0 crates/cli/src/lib.rs | 4 ++-- 6 files changed, 2 insertions(+), 2 deletions(-) rename crates/cli/src/{cli_command.rs => cli_args.rs} (100%) rename crates/cli/src/{cli_command => cli_args}/add.rs (100%) rename crates/cli/src/{cli_command => cli_args}/install.rs (100%) rename crates/cli/src/{cli_command => cli_args}/run.rs (100%) rename crates/cli/src/{cli_command => cli_args}/store.rs (100%) diff --git a/crates/cli/src/cli_command.rs b/crates/cli/src/cli_args.rs similarity index 100% rename from crates/cli/src/cli_command.rs rename to crates/cli/src/cli_args.rs diff --git a/crates/cli/src/cli_command/add.rs b/crates/cli/src/cli_args/add.rs similarity index 100% rename from crates/cli/src/cli_command/add.rs rename to crates/cli/src/cli_args/add.rs diff --git a/crates/cli/src/cli_command/install.rs b/crates/cli/src/cli_args/install.rs similarity index 100% rename from crates/cli/src/cli_command/install.rs rename to crates/cli/src/cli_args/install.rs diff --git a/crates/cli/src/cli_command/run.rs b/crates/cli/src/cli_args/run.rs similarity index 100% rename from crates/cli/src/cli_command/run.rs rename to crates/cli/src/cli_args/run.rs diff --git a/crates/cli/src/cli_command/store.rs b/crates/cli/src/cli_args/store.rs similarity index 100% rename from crates/cli/src/cli_command/store.rs rename to crates/cli/src/cli_args/store.rs diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index b94f041df..4a2bd7bce 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -1,8 +1,8 @@ -mod cli_command; +mod cli_args; mod package_manager; use clap::Parser; -use cli_command::{store::StoreCommand, CliArgs, CliCommand}; +use cli_args::{store::StoreCommand, CliArgs, CliCommand}; use miette::{set_panic_hook, Context, IntoDiagnostic}; use package_manager::PackageManager; use pacquet_diagnostics::enable_tracing_by_env; From 8be20eafefc00c8ee60d0bc566438e0e880f8ff3 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 00:09:52 +0700 Subject: [PATCH 146/210] feat(cli): only load .npmrc when necessary --- crates/cli/src/lib.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index 4a2bd7bce..e152b2b4f 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -14,11 +14,10 @@ pub async fn main() -> miette::Result<()> { enable_tracing_by_env(); set_panic_hook(); let cli = CliArgs::parse(); - let config = Npmrc::current().leak(); - run(cli, config).await + run(cli).await } -async fn run(cli: CliArgs, config: &'static Npmrc) -> miette::Result<()> { +async fn run(cli: CliArgs) -> miette::Result<()> { let package_json_path = cli.dir.join("package.json"); match &cli.command { @@ -27,6 +26,7 @@ async fn run(cli: CliArgs, config: &'static Npmrc) -> miette::Result<()> { PackageJson::init(&package_json_path).wrap_err("initialize package.json")?; } CliCommand::Add(args) => { + let config = Npmrc::current().leak(); let mut package_manager = PackageManager::new(&package_json_path, config) .wrap_err("initializing the package manager")?; // TODO if a package already exists in another dependency group, we don't remove @@ -34,6 +34,7 @@ async fn run(cli: CliArgs, config: &'static Npmrc) -> miette::Result<()> { package_manager.add(args).await.wrap_err("adding a new package")?; } CliCommand::Install(args) => { + let config = Npmrc::current().leak(); let package_manager = PackageManager::new(&package_json_path, config) .wrap_err("initializing the package manager")?; package_manager @@ -83,9 +84,11 @@ async fn run(cli: CliArgs, config: &'static Npmrc) -> miette::Result<()> { panic!("Not implemented") } StoreCommand::Prune => { + let config = Npmrc::current().leak(); pacquet_cafs::prune_sync(&config.store_dir).wrap_err("pruning store")?; } StoreCommand::Path => { + let config = Npmrc::current().leak(); println!("{}", config.store_dir.display()); } }, @@ -104,7 +107,7 @@ mod tests { async fn init_command_should_create_package_json() { let parent_folder = tempdir().unwrap(); let cli = CliArgs::parse_from(["", "-C", parent_folder.path().to_str().unwrap(), "init"]); - run(cli, Npmrc::current().leak()).await.unwrap(); + run(cli).await.unwrap(); assert!(parent_folder.path().join("package.json").exists()); } @@ -115,7 +118,7 @@ mod tests { file.write_all("{}".as_bytes()).unwrap(); assert!(parent_folder.path().join("package.json").exists()); let cli = CliArgs::parse_from(["", "-C", parent_folder.path().to_str().unwrap(), "init"]); - run(cli, Npmrc::current().leak()).await.expect_err("should have thrown"); + run(cli).await.expect_err("should have thrown"); } #[tokio::test] @@ -128,6 +131,6 @@ mod tests { "store", "path", ]); - run(cli, Npmrc::current().leak()).await.unwrap(); + run(cli).await.unwrap(); } } From e15900c5fa3fcb625d87abc704ffc6f07c01327b Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 00:25:42 +0700 Subject: [PATCH 147/210] fix(test): forgot to set current_dir --- crates/cli/tests/add.rs | 2 +- crates/testing-utils/src/bin.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/cli/tests/add.rs b/crates/cli/tests/add.rs index 08b657623..b91390195 100644 --- a/crates/cli/tests/add.rs +++ b/crates/cli/tests/add.rs @@ -14,7 +14,7 @@ where Args::Item: AsRef, { let (mut command, current_dir) = pacquet_with_temp_cwd(); - command.current_dir(current_dir.path()).args(args).assert().success(); + command.args(args).assert().success(); current_dir } diff --git a/crates/testing-utils/src/bin.rs b/crates/testing-utils/src/bin.rs index b0570c89f..e6efa7fec 100644 --- a/crates/testing-utils/src/bin.rs +++ b/crates/testing-utils/src/bin.rs @@ -4,6 +4,7 @@ use tempfile::{tempdir, TempDir}; pub fn pacquet_with_temp_cwd() -> (Command, TempDir) { let current_dir = tempdir().expect("create temporary working directory for pacquet"); - let command = Command::cargo_bin("pacquet").expect("find the pacquet binary"); + let mut command = Command::cargo_bin("pacquet").expect("find the pacquet binary"); + command.current_dir(current_dir.path()); (command, current_dir) } From 7824b31a49b8413e5d6c93906b739b2e6f3f7b48 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 00:42:41 +0700 Subject: [PATCH 148/210] test(cli): init --- crates/cli/src/lib.rs | 19 ------- crates/cli/tests/init.rs | 52 +++++++++++++++++++ .../init__should_create_package_json.snap | 17 ++++++ .../init__should_throw_on_existing_file.snap | 10 ++++ 4 files changed, 79 insertions(+), 19 deletions(-) create mode 100644 crates/cli/tests/init.rs create mode 100644 crates/cli/tests/snapshots/init__should_create_package_json.snap create mode 100644 crates/cli/tests/snapshots/init__should_throw_on_existing_file.snap diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index e152b2b4f..5aa861c6b 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -100,27 +100,8 @@ async fn run(cli: CliArgs) -> miette::Result<()> { #[cfg(test)] mod tests { use super::*; - use std::{fs, io::Write}; use tempfile::tempdir; - #[tokio::test] - async fn init_command_should_create_package_json() { - let parent_folder = tempdir().unwrap(); - let cli = CliArgs::parse_from(["", "-C", parent_folder.path().to_str().unwrap(), "init"]); - run(cli).await.unwrap(); - assert!(parent_folder.path().join("package.json").exists()); - } - - #[tokio::test] - async fn init_command_should_throw_on_existing_file() { - let parent_folder = tempdir().unwrap(); - let mut file = fs::File::create(parent_folder.path().join("package.json")).unwrap(); - file.write_all("{}".as_bytes()).unwrap(); - assert!(parent_folder.path().join("package.json").exists()); - let cli = CliArgs::parse_from(["", "-C", parent_folder.path().to_str().unwrap(), "init"]); - run(cli).await.expect_err("should have thrown"); - } - #[tokio::test] async fn should_get_store_path() { let parent_folder = tempdir().unwrap(); diff --git a/crates/cli/tests/init.rs b/crates/cli/tests/init.rs new file mode 100644 index 000000000..5aa0ce1b5 --- /dev/null +++ b/crates/cli/tests/init.rs @@ -0,0 +1,52 @@ +use assert_cmd::prelude::*; +use pacquet_testing_utils::{bin::pacquet_with_temp_cwd, fs::get_filenames_in_folder}; +use pretty_assertions::assert_eq; +use std::{env, ffi::OsStr, fs}; +use tempfile::TempDir; + +pub fn exec_pacquet_in_temp_cwd(args: Args) -> TempDir +where + Args: IntoIterator, + Args::Item: AsRef, +{ + let (mut command, current_dir) = pacquet_with_temp_cwd(); + command.args(args).assert().success(); + current_dir +} + +#[test] +fn should_create_package_json() { + let dir = exec_pacquet_in_temp_cwd(["init"]); + + let package_json_path = dir.path().join("package.json"); + dbg!(&package_json_path); + + eprintln!("Content of package.json"); + let package_json_content = + fs::read_to_string(&package_json_path).expect("read from package.json"); + insta::assert_snapshot!(package_json_content); + + eprintln!("Created files"); + assert_eq!(get_filenames_in_folder(dir.path()), ["package.json"]); +} + +#[test] +fn should_throw_on_existing_file() { + let (mut command, dir) = pacquet_with_temp_cwd(); + + let package_json_path = dir.path().join("package.json"); + dbg!(&package_json_path); + + eprintln!("Creating package.json..."); + fs::write(&package_json_path, "{}").expect("write to package.json"); + + eprintln!("Executing pacquet init..."); + let output = command.arg("init").output().expect("execute pacquet init"); + dbg!(&output); + + eprintln!("Exit status code"); + assert!(!output.status.success()); + + eprintln!("Stderr"); + insta::assert_snapshot!(String::from_utf8_lossy(&output.stderr).trim_end()); +} diff --git a/crates/cli/tests/snapshots/init__should_create_package_json.snap b/crates/cli/tests/snapshots/init__should_create_package_json.snap new file mode 100644 index 000000000..619dab683 --- /dev/null +++ b/crates/cli/tests/snapshots/init__should_create_package_json.snap @@ -0,0 +1,17 @@ +--- +source: crates/cli/tests/init.rs +assertion_line: 31 +expression: package_json_content +--- +{ + "name": "", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/crates/cli/tests/snapshots/init__should_throw_on_existing_file.snap b/crates/cli/tests/snapshots/init__should_throw_on_existing_file.snap new file mode 100644 index 000000000..99bad67dc --- /dev/null +++ b/crates/cli/tests/snapshots/init__should_throw_on_existing_file.snap @@ -0,0 +1,10 @@ +--- +source: crates/cli/tests/init.rs +assertion_line: 56 +expression: "String::from_utf8_lossy(&output.stderr).trim_end()" +--- +Error: pacquet_package_json::already_exist_error + + × initialize package.json + ╰─▶ package.json file already exists + help: Your current working directory already has a package.json file. From 086af30895c19487e6da0622bf65d87ab5644dbf Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 00:45:32 +0700 Subject: [PATCH 149/210] refactor(test): share code --- crates/cli/tests/_utils.rs | 14 ++++++++++++++ crates/cli/tests/add.rs | 22 +++++----------------- crates/cli/tests/init.rs | 17 ++++------------- 3 files changed, 23 insertions(+), 30 deletions(-) create mode 100644 crates/cli/tests/_utils.rs diff --git a/crates/cli/tests/_utils.rs b/crates/cli/tests/_utils.rs new file mode 100644 index 000000000..20a140b44 --- /dev/null +++ b/crates/cli/tests/_utils.rs @@ -0,0 +1,14 @@ +use assert_cmd::prelude::*; +use pacquet_testing_utils::bin::pacquet_with_temp_cwd; +use std::ffi::OsStr; +use tempfile::TempDir; + +pub fn exec_pacquet_in_temp_cwd(args: Args) -> TempDir +where + Args: IntoIterator, + Args::Item: AsRef, +{ + let (mut command, current_dir) = pacquet_with_temp_cwd(); + command.args(args).assert().success(); + current_dir +} diff --git a/crates/cli/tests/add.rs b/crates/cli/tests/add.rs index b91390195..86380db25 100644 --- a/crates/cli/tests/add.rs +++ b/crates/cli/tests/add.rs @@ -1,22 +1,10 @@ -use assert_cmd::prelude::*; +pub mod _utils; +pub use _utils::*; + use pacquet_package_json::{DependencyGroup, PackageJson}; -use pacquet_testing_utils::{ - bin::pacquet_with_temp_cwd, - fs::{get_all_folders, get_filenames_in_folder}, -}; +use pacquet_testing_utils::fs::{get_all_folders, get_filenames_in_folder}; use pretty_assertions::assert_eq; -use std::{env, ffi::OsStr, fs}; -use tempfile::TempDir; - -pub fn exec_pacquet_in_temp_cwd(args: Args) -> TempDir -where - Args: IntoIterator, - Args::Item: AsRef, -{ - let (mut command, current_dir) = pacquet_with_temp_cwd(); - command.args(args).assert().success(); - current_dir -} +use std::{env, fs}; #[test] fn should_install_all_dependencies() { diff --git a/crates/cli/tests/init.rs b/crates/cli/tests/init.rs index 5aa0ce1b5..41c5f8160 100644 --- a/crates/cli/tests/init.rs +++ b/crates/cli/tests/init.rs @@ -1,18 +1,9 @@ -use assert_cmd::prelude::*; +pub mod _utils; +pub use _utils::*; + use pacquet_testing_utils::{bin::pacquet_with_temp_cwd, fs::get_filenames_in_folder}; use pretty_assertions::assert_eq; -use std::{env, ffi::OsStr, fs}; -use tempfile::TempDir; - -pub fn exec_pacquet_in_temp_cwd(args: Args) -> TempDir -where - Args: IntoIterator, - Args::Item: AsRef, -{ - let (mut command, current_dir) = pacquet_with_temp_cwd(); - command.args(args).assert().success(); - current_dir -} +use std::{env, fs}; #[test] fn should_create_package_json() { From 58de7e05fe8c1ff0d58cc082e5c635133c7411a3 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 00:47:01 +0700 Subject: [PATCH 150/210] test(cli): remove nonsensical test --- crates/cli/src/lib.rs | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index 5aa861c6b..a95bdb4df 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -96,22 +96,3 @@ async fn run(cli: CliArgs) -> miette::Result<()> { Ok(()) } - -#[cfg(test)] -mod tests { - use super::*; - use tempfile::tempdir; - - #[tokio::test] - async fn should_get_store_path() { - let parent_folder = tempdir().unwrap(); - let cli = CliArgs::parse_from([ - "", - "-C", - parent_folder.path().to_str().unwrap(), - "store", - "path", - ]); - run(cli).await.unwrap(); - } -} From 73f6c08c3993cd46e0fdfe0cf0442c4a56a6092a Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 00:57:48 +0700 Subject: [PATCH 151/210] test(cli): pacquet store path --- crates/cli/tests/store.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 crates/cli/tests/store.rs diff --git a/crates/cli/tests/store.rs b/crates/cli/tests/store.rs new file mode 100644 index 000000000..bb317ce2c --- /dev/null +++ b/crates/cli/tests/store.rs @@ -0,0 +1,24 @@ +use pacquet_testing_utils::bin::pacquet_with_temp_cwd; +use pretty_assertions::assert_eq; +use std::fs; + +#[test] +fn store_path_should_return_store_dir_from_npmrc() { + let (mut command, dir) = pacquet_with_temp_cwd(); + + eprintln!("Creating .npmrc..."); + fs::write(dir.path().join(".npmrc"), "store-dir=foo/bar").expect("write to .npmrc"); + + eprintln!("Executing pacquet store path..."); + let output = command.args(["store", "path"]).output().expect("run pacquet store path"); + dbg!(&output); + + eprintln!("Exit status code"); + assert!(output.status.success()); + + eprintln!("Stdout"); + assert_eq!( + String::from_utf8_lossy(&output.stdout).trim_end(), + dir.path().join("foo/bar").to_string_lossy(), + ); +} From 0a2fd52fe9d97a90b2676db205b54e53555c3033 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 01:03:39 +0700 Subject: [PATCH 152/210] refactor(test): remove mut --- Cargo.lock | 8 ++++++++ Cargo.toml | 1 + crates/cli/Cargo.toml | 1 + crates/cli/tests/_utils.rs | 5 +++-- crates/cli/tests/init.rs | 5 +++-- crates/cli/tests/install.rs | 5 +++-- crates/cli/tests/store.rs | 5 +++-- crates/testing-utils/Cargo.toml | 7 ++++--- crates/testing-utils/src/bin.rs | 6 ++++-- 9 files changed, 30 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 41199df6e..1b707cbf0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -304,6 +304,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "command-extra" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1b4fe32ea3f2a8d975b6c5cdd3f02ac358f471ca24dbb18d7a4ca58b3193d2d" + [[package]] name = "console" version = "0.15.7" @@ -1290,6 +1296,7 @@ version = "0.0.1" dependencies = [ "assert_cmd", "clap", + "command-extra", "insta", "miette", "pacquet_cafs", @@ -1482,6 +1489,7 @@ name = "pacquet_testing_utils" version = "0.0.0" dependencies = [ "assert_cmd", + "command-extra", "junction", "tempfile", "walkdir", diff --git a/Cargo.toml b/Cargo.toml index d6a807dd6..32dcea25a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,7 @@ pacquet_diagnostics = { path = "crates/diagnostics" } # Dependencies async-recursion = { version = "1.0.5" } clap = { version = "4", features = ["derive", "string"] } +command-extra = { version = "1.0.0" } dashmap = { version = "5.5.3" } derive_more = { version = "0.99.17" } home = { version = "0.5.5" } diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 33728f2bb..7f23e9b15 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -38,6 +38,7 @@ tracing = { workspace = true } pacquet_testing_utils = { workspace = true } assert_cmd = { workspace = true } +command-extra = { workspace = true } insta = { workspace = true } pretty_assertions = { workspace = true } serde_json = { workspace = true } diff --git a/crates/cli/tests/_utils.rs b/crates/cli/tests/_utils.rs index 20a140b44..60a7de59d 100644 --- a/crates/cli/tests/_utils.rs +++ b/crates/cli/tests/_utils.rs @@ -1,4 +1,5 @@ use assert_cmd::prelude::*; +use command_extra::CommandExtra; use pacquet_testing_utils::bin::pacquet_with_temp_cwd; use std::ffi::OsStr; use tempfile::TempDir; @@ -8,7 +9,7 @@ where Args: IntoIterator, Args::Item: AsRef, { - let (mut command, current_dir) = pacquet_with_temp_cwd(); - command.args(args).assert().success(); + let (command, current_dir) = pacquet_with_temp_cwd(); + command.with_args(args).assert().success(); current_dir } diff --git a/crates/cli/tests/init.rs b/crates/cli/tests/init.rs index 41c5f8160..01bb9923b 100644 --- a/crates/cli/tests/init.rs +++ b/crates/cli/tests/init.rs @@ -1,6 +1,7 @@ pub mod _utils; pub use _utils::*; +use command_extra::CommandExtra; use pacquet_testing_utils::{bin::pacquet_with_temp_cwd, fs::get_filenames_in_folder}; use pretty_assertions::assert_eq; use std::{env, fs}; @@ -23,7 +24,7 @@ fn should_create_package_json() { #[test] fn should_throw_on_existing_file() { - let (mut command, dir) = pacquet_with_temp_cwd(); + let (command, dir) = pacquet_with_temp_cwd(); let package_json_path = dir.path().join("package.json"); dbg!(&package_json_path); @@ -32,7 +33,7 @@ fn should_throw_on_existing_file() { fs::write(&package_json_path, "{}").expect("write to package.json"); eprintln!("Executing pacquet init..."); - let output = command.arg("init").output().expect("execute pacquet init"); + let output = command.with_arg("init").output().expect("execute pacquet init"); dbg!(&output); eprintln!("Exit status code"); diff --git a/crates/cli/tests/install.rs b/crates/cli/tests/install.rs index f334ee875..215361be2 100644 --- a/crates/cli/tests/install.rs +++ b/crates/cli/tests/install.rs @@ -1,4 +1,5 @@ use assert_cmd::prelude::*; +use command_extra::CommandExtra; use pacquet_testing_utils::{ bin::pacquet_with_temp_cwd, fs::{get_all_folders, is_symlink_or_junction}, @@ -7,7 +8,7 @@ use std::fs; #[test] fn should_install_dependencies() { - let (mut command, dir) = pacquet_with_temp_cwd(); + let (command, dir) = pacquet_with_temp_cwd(); eprintln!("Creating package.json..."); let package_json_path = dir.path().join("package.json"); @@ -22,7 +23,7 @@ fn should_install_dependencies() { fs::write(&package_json_path, package_json_content.to_string()).expect("write to package.json"); eprintln!("Executing command..."); - command.current_dir(dir.path()).arg("install").assert().success(); + command.with_current_dir(dir.path()).with_arg("install").assert().success(); eprintln!("Make sure the package is installed"); assert!(is_symlink_or_junction(&dir.path().join("node_modules/is-odd")).unwrap()); diff --git a/crates/cli/tests/store.rs b/crates/cli/tests/store.rs index bb317ce2c..4b23616e9 100644 --- a/crates/cli/tests/store.rs +++ b/crates/cli/tests/store.rs @@ -1,16 +1,17 @@ +use command_extra::CommandExtra; use pacquet_testing_utils::bin::pacquet_with_temp_cwd; use pretty_assertions::assert_eq; use std::fs; #[test] fn store_path_should_return_store_dir_from_npmrc() { - let (mut command, dir) = pacquet_with_temp_cwd(); + let (command, dir) = pacquet_with_temp_cwd(); eprintln!("Creating .npmrc..."); fs::write(dir.path().join(".npmrc"), "store-dir=foo/bar").expect("write to .npmrc"); eprintln!("Executing pacquet store path..."); - let output = command.args(["store", "path"]).output().expect("run pacquet store path"); + let output = command.with_args(["store", "path"]).output().expect("run pacquet store path"); dbg!(&output); eprintln!("Exit status code"); diff --git a/crates/testing-utils/Cargo.toml b/crates/testing-utils/Cargo.toml index d9e361c47..b67d0e73a 100644 --- a/crates/testing-utils/Cargo.toml +++ b/crates/testing-utils/Cargo.toml @@ -11,9 +11,10 @@ license.workspace = true repository.workspace = true [dependencies] -assert_cmd = { workspace = true } -tempfile = { workspace = true } -walkdir = { workspace = true } +assert_cmd = { workspace = true } +command-extra = { workspace = true } +tempfile = { workspace = true } +walkdir = { workspace = true } [target.'cfg(windows)'.dependencies] junction = { workspace = true } diff --git a/crates/testing-utils/src/bin.rs b/crates/testing-utils/src/bin.rs index e6efa7fec..c51ceb86e 100644 --- a/crates/testing-utils/src/bin.rs +++ b/crates/testing-utils/src/bin.rs @@ -1,10 +1,12 @@ use assert_cmd::prelude::*; +use command_extra::CommandExtra; use std::process::Command; use tempfile::{tempdir, TempDir}; pub fn pacquet_with_temp_cwd() -> (Command, TempDir) { let current_dir = tempdir().expect("create temporary working directory for pacquet"); - let mut command = Command::cargo_bin("pacquet").expect("find the pacquet binary"); - command.current_dir(current_dir.path()); + let command = Command::cargo_bin("pacquet") + .expect("find the pacquet binary") + .with_current_dir(current_dir.path()); (command, current_dir) } From 15a89465d0345f667b9e1e48ba75774544fb9094 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 01:04:45 +0700 Subject: [PATCH 153/210] refactor(test): remove unnecessary action --- crates/cli/tests/install.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli/tests/install.rs b/crates/cli/tests/install.rs index 215361be2..9edddd1e6 100644 --- a/crates/cli/tests/install.rs +++ b/crates/cli/tests/install.rs @@ -23,7 +23,7 @@ fn should_install_dependencies() { fs::write(&package_json_path, package_json_content.to_string()).expect("write to package.json"); eprintln!("Executing command..."); - command.with_current_dir(dir.path()).with_arg("install").assert().success(); + command.with_arg("install").assert().success(); eprintln!("Make sure the package is installed"); assert!(is_symlink_or_junction(&dir.path().join("node_modules/is-odd")).unwrap()); From cabff79da5639fcf2604ea16c4e4b5f0e7c1b222 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 01:28:54 +0700 Subject: [PATCH 154/210] refactor(cli): attach code to respective args --- crates/cli/src/cli_args.rs | 72 +++++++++++++++++++++++ crates/cli/src/cli_args/add.rs | 15 +++++ crates/cli/src/cli_args/install.rs | 12 ++++ crates/cli/src/lib.rs | 91 +----------------------------- 4 files changed, 102 insertions(+), 88 deletions(-) diff --git a/crates/cli/src/cli_args.rs b/crates/cli/src/cli_args.rs index fab2a0726..951314380 100644 --- a/crates/cli/src/cli_args.rs +++ b/crates/cli/src/cli_args.rs @@ -6,6 +6,10 @@ pub mod store; use add::AddArgs; use clap::{Parser, Subcommand}; use install::InstallArgs; +use miette::Context; +use pacquet_executor::execute_shell; +use pacquet_npmrc::Npmrc; +use pacquet_package_json::PackageJson; use run::RunArgs; use std::path::PathBuf; use store::StoreCommand; @@ -43,3 +47,71 @@ pub enum CliCommand { #[clap(subcommand)] Store(StoreCommand), } + +impl CliArgs { + /// Execute the command + pub async fn run(&self) -> miette::Result<()> { + let package_json_path = self.dir.join("package.json"); + + match &self.command { + CliCommand::Init => { + // init command throws an error if package.json file exist. + PackageJson::init(&package_json_path).wrap_err("initialize package.json")?; + } + CliCommand::Add(args) => return args.run(&package_json_path).await, + CliCommand::Install(args) => return args.run(&package_json_path).await, + CliCommand::Test => { + let package_json = PackageJson::from_path(package_json_path) + .wrap_err("getting the package.json in current directory")?; + if let Some(script) = package_json.script("test", false)? { + execute_shell(script) + .wrap_err(format!("executing command: \"{0}\"", script))?; + } + } + CliCommand::Run(args) => { + let package_json = PackageJson::from_path(package_json_path) + .wrap_err("getting the package.json in current directory")?; + if let Some(script) = package_json.script(&args.command, args.if_present)? { + let mut command = script.to_string(); + // append an empty space between script and additional args + command.push(' '); + // then append the additional args + command.push_str(&args.args.join(" ")); + execute_shell(command.trim())?; + } + } + CliCommand::Start => { + // Runs an arbitrary command specified in the package's start property of its scripts + // object. If no start property is specified on the scripts object, it will attempt to + // run node server.js as a default, failing if neither are present. + // The intended usage of the property is to specify a command that starts your program. + let package_json = PackageJson::from_path(package_json_path) + .wrap_err("getting the package.json in current directory")?; + let command = if let Some(script) = package_json.script("start", true)? { + script + } else { + "node server.js" + }; + execute_shell(command).wrap_err(format!("executing command: \"{0}\"", command))?; + } + CliCommand::Store(command) => match command { + StoreCommand::Store => { + panic!("Not implemented") + } + StoreCommand::Add => { + panic!("Not implemented") + } + StoreCommand::Prune => { + let config = Npmrc::current().leak(); + pacquet_cafs::prune_sync(&config.store_dir).wrap_err("pruning store")?; + } + StoreCommand::Path => { + let config = Npmrc::current().leak(); + println!("{}", config.store_dir.display()); + } + }, + } + + Ok(()) + } +} diff --git a/crates/cli/src/cli_args/add.rs b/crates/cli/src/cli_args/add.rs index ab3c9f370..d0bb7bc90 100644 --- a/crates/cli/src/cli_args/add.rs +++ b/crates/cli/src/cli_args/add.rs @@ -1,7 +1,10 @@ use crate::package_manager::{PackageManager, PackageManagerError}; use clap::Args; +use miette::Context; +use pacquet_npmrc::Npmrc; use pacquet_package_json::DependencyGroup; use pacquet_package_manager::Add; +use std::path::Path; #[derive(Debug, Args)] pub struct AddDependencyOptions { @@ -53,6 +56,18 @@ pub struct AddArgs { pub virtual_store_dir: String, } +impl AddArgs { + /// Execute the subcommand. + pub async fn run(&self, package_json_path: &Path) -> miette::Result<()> { + let config = Npmrc::current().leak(); + let mut package_manager = PackageManager::new(package_json_path, config) + .wrap_err("initializing the package manager")?; + // TODO if a package already exists in another dependency group, we don't remove + // the existing entry. + package_manager.add(self).await.wrap_err("adding a new package") + } +} + impl PackageManager { pub async fn add(&mut self, args: &AddArgs) -> Result<(), PackageManagerError> { let PackageManager { config, package_json, lockfile, http_client, tarball_cache } = self; diff --git a/crates/cli/src/cli_args/install.rs b/crates/cli/src/cli_args/install.rs index 6fe15dd17..d7fc200fd 100644 --- a/crates/cli/src/cli_args/install.rs +++ b/crates/cli/src/cli_args/install.rs @@ -1,7 +1,10 @@ use crate::package_manager::{PackageManager, PackageManagerError}; use clap::Args; +use miette::{Context, IntoDiagnostic}; +use pacquet_npmrc::Npmrc; use pacquet_package_json::DependencyGroup; use pacquet_package_manager::Install; +use std::path::Path; #[derive(Debug, Args)] pub struct InstallDependencyOptions { @@ -47,6 +50,15 @@ pub struct InstallArgs { pub frozen_lockfile: bool, } +impl InstallArgs { + pub async fn run(&self, package_json_path: &Path) -> miette::Result<()> { + let config = Npmrc::current().leak(); + let package_manager = PackageManager::new(package_json_path, config) + .wrap_err("initializing the package manager")?; + package_manager.install(self).await.into_diagnostic().wrap_err("installing dependencies") + } +} + impl PackageManager { /// Jobs of the `install` command. pub async fn install(&self, args: &InstallArgs) -> Result<(), PackageManagerError> { diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index a95bdb4df..bf8516f46 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -2,97 +2,12 @@ mod cli_args; mod package_manager; use clap::Parser; -use cli_args::{store::StoreCommand, CliArgs, CliCommand}; -use miette::{set_panic_hook, Context, IntoDiagnostic}; -use package_manager::PackageManager; +use cli_args::CliArgs; +use miette::set_panic_hook; use pacquet_diagnostics::enable_tracing_by_env; -use pacquet_executor::execute_shell; -use pacquet_npmrc::Npmrc; -use pacquet_package_json::PackageJson; pub async fn main() -> miette::Result<()> { enable_tracing_by_env(); set_panic_hook(); - let cli = CliArgs::parse(); - run(cli).await -} - -async fn run(cli: CliArgs) -> miette::Result<()> { - let package_json_path = cli.dir.join("package.json"); - - match &cli.command { - CliCommand::Init => { - // init command throws an error if package.json file exist. - PackageJson::init(&package_json_path).wrap_err("initialize package.json")?; - } - CliCommand::Add(args) => { - let config = Npmrc::current().leak(); - let mut package_manager = PackageManager::new(&package_json_path, config) - .wrap_err("initializing the package manager")?; - // TODO if a package already exists in another dependency group, we don't remove - // the existing entry. - package_manager.add(args).await.wrap_err("adding a new package")?; - } - CliCommand::Install(args) => { - let config = Npmrc::current().leak(); - let package_manager = PackageManager::new(&package_json_path, config) - .wrap_err("initializing the package manager")?; - package_manager - .install(args) - .await - .into_diagnostic() - .wrap_err("installing dependencies")?; - } - CliCommand::Test => { - let package_json = PackageJson::from_path(package_json_path) - .wrap_err("getting the package.json in current directory")?; - if let Some(script) = package_json.script("test", false)? { - execute_shell(script).wrap_err(format!("executing command: \"{0}\"", script))?; - } - } - CliCommand::Run(args) => { - let package_json = PackageJson::from_path(package_json_path) - .wrap_err("getting the package.json in current directory")?; - if let Some(script) = package_json.script(&args.command, args.if_present)? { - let mut command = script.to_string(); - // append an empty space between script and additional args - command.push(' '); - // then append the additional args - command.push_str(&args.args.join(" ")); - execute_shell(command.trim())?; - } - } - CliCommand::Start => { - // Runs an arbitrary command specified in the package's start property of its scripts - // object. If no start property is specified on the scripts object, it will attempt to - // run node server.js as a default, failing if neither are present. - // The intended usage of the property is to specify a command that starts your program. - let package_json = PackageJson::from_path(package_json_path) - .wrap_err("getting the package.json in current directory")?; - let command = if let Some(script) = package_json.script("start", true)? { - script - } else { - "node server.js" - }; - execute_shell(command).wrap_err(format!("executing command: \"{0}\"", command))?; - } - CliCommand::Store(command) => match command { - StoreCommand::Store => { - panic!("Not implemented") - } - StoreCommand::Add => { - panic!("Not implemented") - } - StoreCommand::Prune => { - let config = Npmrc::current().leak(); - pacquet_cafs::prune_sync(&config.store_dir).wrap_err("pruning store")?; - } - StoreCommand::Path => { - let config = Npmrc::current().leak(); - println!("{}", config.store_dir.display()); - } - }, - } - - Ok(()) + CliArgs::parse().run().await } From e1ee4eb2919d3040a2d0faa6c27a16008c94a979 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 01:39:26 +0700 Subject: [PATCH 155/210] refactor(cli): remove methods from PackageManager --- crates/cli/src/cli_args/add.rs | 23 ++++++++++------------- crates/cli/src/cli_args/install.rs | 15 +++++---------- 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/crates/cli/src/cli_args/add.rs b/crates/cli/src/cli_args/add.rs index d0bb7bc90..b7e368cd8 100644 --- a/crates/cli/src/cli_args/add.rs +++ b/crates/cli/src/cli_args/add.rs @@ -4,7 +4,7 @@ use miette::Context; use pacquet_npmrc::Npmrc; use pacquet_package_json::DependencyGroup; use pacquet_package_manager::Add; -use std::path::Path; +use std::path::{Path, PathBuf}; #[derive(Debug, Args)] pub struct AddDependencyOptions { @@ -53,7 +53,7 @@ pub struct AddArgs { /// The directory with links to the store (default is node_modules/.pacquet). /// All direct and indirect dependencies of the project are linked into this directory #[clap(long = "virtual-store-dir", default_value = "node_modules/.pacquet")] - pub virtual_store_dir: String, + pub virtual_store_dir: Option, // TODO: make use of this } impl AddArgs { @@ -62,15 +62,11 @@ impl AddArgs { let config = Npmrc::current().leak(); let mut package_manager = PackageManager::new(package_json_path, config) .wrap_err("initializing the package manager")?; - // TODO if a package already exists in another dependency group, we don't remove - // the existing entry. - package_manager.add(self).await.wrap_err("adding a new package") - } -} -impl PackageManager { - pub async fn add(&mut self, args: &AddArgs) -> Result<(), PackageManagerError> { - let PackageManager { config, package_json, lockfile, http_client, tarball_cache } = self; + // TODO: if a package already exists in another dependency group, don't remove the existing entry. + + let PackageManager { config, package_json, lockfile, http_client, tarball_cache } = + &mut package_manager; Add { tarball_cache, @@ -78,13 +74,14 @@ impl PackageManager { config, package_json, lockfile: lockfile.as_ref(), - list_dependency_groups: || args.dependency_options.dependency_groups(), - package: &args.package, - save_exact: args.save_exact, + list_dependency_groups: || self.dependency_options.dependency_groups(), + package: &self.package, + save_exact: self.save_exact, } .run() .await .map_err(PackageManagerError::AddCommand) + .wrap_err("adding a new package") } } diff --git a/crates/cli/src/cli_args/install.rs b/crates/cli/src/cli_args/install.rs index d7fc200fd..a45510b78 100644 --- a/crates/cli/src/cli_args/install.rs +++ b/crates/cli/src/cli_args/install.rs @@ -1,6 +1,6 @@ -use crate::package_manager::{PackageManager, PackageManagerError}; +use crate::package_manager::PackageManager; use clap::Args; -use miette::{Context, IntoDiagnostic}; +use miette::Context; use pacquet_npmrc::Npmrc; use pacquet_package_json::DependencyGroup; use pacquet_package_manager::Install; @@ -55,15 +55,10 @@ impl InstallArgs { let config = Npmrc::current().leak(); let package_manager = PackageManager::new(package_json_path, config) .wrap_err("initializing the package manager")?; - package_manager.install(self).await.into_diagnostic().wrap_err("installing dependencies") - } -} -impl PackageManager { - /// Jobs of the `install` command. - pub async fn install(&self, args: &InstallArgs) -> Result<(), PackageManagerError> { - let PackageManager { config, http_client, tarball_cache, lockfile, package_json } = self; - let InstallArgs { dependency_options, frozen_lockfile } = args; + let PackageManager { config, http_client, tarball_cache, lockfile, package_json } = + &package_manager; + let InstallArgs { dependency_options, frozen_lockfile } = self; Install { tarball_cache, From 3dd979465f3e4ad5d55f13523dc3846ac6ce7254 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 01:46:54 +0700 Subject: [PATCH 156/210] refactor: rename `PackageManager` to `State` --- crates/cli/src/cli_args/add.rs | 9 ++++---- crates/cli/src/cli_args/install.rs | 9 ++++---- crates/cli/src/lib.rs | 2 +- .../cli/src/{package_manager.rs => state.rs} | 23 ++++++++----------- 4 files changed, 18 insertions(+), 25 deletions(-) rename crates/cli/src/{package_manager.rs => state.rs} (83%) diff --git a/crates/cli/src/cli_args/add.rs b/crates/cli/src/cli_args/add.rs index b7e368cd8..ca2ce64bb 100644 --- a/crates/cli/src/cli_args/add.rs +++ b/crates/cli/src/cli_args/add.rs @@ -1,4 +1,4 @@ -use crate::package_manager::{PackageManager, PackageManagerError}; +use crate::state::State; use clap::Args; use miette::Context; use pacquet_npmrc::Npmrc; @@ -60,12 +60,12 @@ impl AddArgs { /// Execute the subcommand. pub async fn run(&self, package_json_path: &Path) -> miette::Result<()> { let config = Npmrc::current().leak(); - let mut package_manager = PackageManager::new(package_json_path, config) - .wrap_err("initializing the package manager")?; + let mut package_manager = + State::init(package_json_path, config).wrap_err("initializing the package manager")?; // TODO: if a package already exists in another dependency group, don't remove the existing entry. - let PackageManager { config, package_json, lockfile, http_client, tarball_cache } = + let State { config, package_json, lockfile, http_client, tarball_cache } = &mut package_manager; Add { @@ -80,7 +80,6 @@ impl AddArgs { } .run() .await - .map_err(PackageManagerError::AddCommand) .wrap_err("adding a new package") } } diff --git a/crates/cli/src/cli_args/install.rs b/crates/cli/src/cli_args/install.rs index a45510b78..170d282a3 100644 --- a/crates/cli/src/cli_args/install.rs +++ b/crates/cli/src/cli_args/install.rs @@ -1,4 +1,4 @@ -use crate::package_manager::PackageManager; +use crate::state::State; use clap::Args; use miette::Context; use pacquet_npmrc::Npmrc; @@ -53,11 +53,10 @@ pub struct InstallArgs { impl InstallArgs { pub async fn run(&self, package_json_path: &Path) -> miette::Result<()> { let config = Npmrc::current().leak(); - let package_manager = PackageManager::new(package_json_path, config) - .wrap_err("initializing the package manager")?; + let package_manager = + State::init(package_json_path, config).wrap_err("initializing the package manager")?; - let PackageManager { config, http_client, tarball_cache, lockfile, package_json } = - &package_manager; + let State { config, http_client, tarball_cache, lockfile, package_json } = &package_manager; let InstallArgs { dependency_options, frozen_lockfile } = self; Install { diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index bf8516f46..b0cd27ee2 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -1,5 +1,5 @@ mod cli_args; -mod package_manager; +mod state; use clap::Parser; use cli_args::CliArgs; diff --git a/crates/cli/src/package_manager.rs b/crates/cli/src/state.rs similarity index 83% rename from crates/cli/src/package_manager.rs rename to crates/cli/src/state.rs index a2974a97c..85eee0120 100644 --- a/crates/cli/src/package_manager.rs +++ b/crates/cli/src/state.rs @@ -2,7 +2,6 @@ use miette::Diagnostic; use pacquet_lockfile::{LoadLockfileError, Lockfile}; use pacquet_npmrc::Npmrc; use pacquet_package_json::{PackageJson, PackageJsonError}; -use pacquet_package_manager::AddError; use pacquet_tarball::Cache; use pipe_trait::Pipe; use std::path::PathBuf; @@ -10,7 +9,7 @@ use thiserror::Error; #[derive(Error, Debug, Diagnostic)] #[non_exhaustive] -pub enum PackageManagerError { +pub enum InitStateError { #[error(transparent)] #[diagnostic(transparent)] LoadPackageJson(PackageJsonError), @@ -18,33 +17,29 @@ pub enum PackageManagerError { #[error(transparent)] #[diagnostic(transparent)] LoadLockfile(LoadLockfileError), - - #[error(transparent)] - #[diagnostic(transparent)] - AddCommand(AddError), } -pub struct PackageManager { +pub struct State { pub config: &'static Npmrc, pub package_json: PackageJson, pub lockfile: Option, pub http_client: reqwest::Client, - pub(crate) tarball_cache: Cache, + pub tarball_cache: Cache, } -impl PackageManager { - pub fn new>( +impl State { + pub fn init>( package_json_path: P, config: &'static Npmrc, - ) -> Result { - Ok(PackageManager { + ) -> Result { + Ok(State { config, package_json: package_json_path .into() .pipe(PackageJson::create_if_needed) - .map_err(PackageManagerError::LoadPackageJson)?, + .map_err(InitStateError::LoadPackageJson)?, lockfile: call_load_lockfile(config.lockfile, Lockfile::load_from_current_dir) - .map_err(PackageManagerError::LoadLockfile)?, + .map_err(InitStateError::LoadLockfile)?, http_client: reqwest::Client::new(), tarball_cache: Cache::new(), }) From 1d183db74c11be7e2a43d234b62e03b55413db48 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 01:47:31 +0700 Subject: [PATCH 157/210] refactor: use --- crates/cli/src/state.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/cli/src/state.rs b/crates/cli/src/state.rs index 85eee0120..58039c92a 100644 --- a/crates/cli/src/state.rs +++ b/crates/cli/src/state.rs @@ -4,6 +4,7 @@ use pacquet_npmrc::Npmrc; use pacquet_package_json::{PackageJson, PackageJsonError}; use pacquet_tarball::Cache; use pipe_trait::Pipe; +use reqwest::Client; use std::path::PathBuf; use thiserror::Error; @@ -23,7 +24,7 @@ pub struct State { pub config: &'static Npmrc, pub package_json: PackageJson, pub lockfile: Option, - pub http_client: reqwest::Client, + pub http_client: Client, pub tarball_cache: Cache, } @@ -40,7 +41,7 @@ impl State { .map_err(InitStateError::LoadPackageJson)?, lockfile: call_load_lockfile(config.lockfile, Lockfile::load_from_current_dir) .map_err(InitStateError::LoadLockfile)?, - http_client: reqwest::Client::new(), + http_client: Client::new(), tarball_cache: Cache::new(), }) } From 6d4df4843a3aafca4701354f2cb118ebc042f7eb Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 01:56:57 +0700 Subject: [PATCH 158/210] feat(npmrc): PackageJson::path --- crates/package_json/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/package_json/src/lib.rs b/crates/package_json/src/lib.rs index bfa041cee..5471dc646 100644 --- a/crates/package_json/src/lib.rs +++ b/crates/package_json/src/lib.rs @@ -126,6 +126,10 @@ impl PackageJson { Ok(PackageJson { path, value }) } + pub fn path(&self) -> &Path { + &self.path + } + pub fn value(&self) -> &Value { &self.value } From 7dbf11a8152da795141f179176fe94317a27422e Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 01:57:18 +0700 Subject: [PATCH 159/210] feat(npmrc): lifetime --- crates/package_json/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/package_json/src/lib.rs b/crates/package_json/src/lib.rs index 5471dc646..de0065a75 100644 --- a/crates/package_json/src/lib.rs +++ b/crates/package_json/src/lib.rs @@ -126,11 +126,11 @@ impl PackageJson { Ok(PackageJson { path, value }) } - pub fn path(&self) -> &Path { + pub fn path(&self) -> &'_ Path { &self.path } - pub fn value(&self) -> &Value { + pub fn value(&self) -> &'_ Value { &self.value } From 5189c825eacfa5bab06147874563d9b4f29de486 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 02:08:36 +0700 Subject: [PATCH 160/210] refactor(cli): pass the state --- crates/cli/src/cli_args.rs | 9 +++++++-- crates/cli/src/cli_args/add.rs | 14 ++++---------- crates/cli/src/cli_args/install.rs | 13 +++---------- crates/cli/src/lib.rs | 1 + 4 files changed, 15 insertions(+), 22 deletions(-) diff --git a/crates/cli/src/cli_args.rs b/crates/cli/src/cli_args.rs index 951314380..c4430b154 100644 --- a/crates/cli/src/cli_args.rs +++ b/crates/cli/src/cli_args.rs @@ -3,6 +3,7 @@ pub mod install; pub mod run; pub mod store; +use crate::State; use add::AddArgs; use clap::{Parser, Subcommand}; use install::InstallArgs; @@ -52,14 +53,18 @@ impl CliArgs { /// Execute the command pub async fn run(&self) -> miette::Result<()> { let package_json_path = self.dir.join("package.json"); + let state = || { + State::init(&package_json_path, Npmrc::current().leak()) + .wrap_err("initialize the state") + }; match &self.command { CliCommand::Init => { // init command throws an error if package.json file exist. PackageJson::init(&package_json_path).wrap_err("initialize package.json")?; } - CliCommand::Add(args) => return args.run(&package_json_path).await, - CliCommand::Install(args) => return args.run(&package_json_path).await, + CliCommand::Add(args) => return args.run(state()?).await, + CliCommand::Install(args) => return args.run(state()?).await, CliCommand::Test => { let package_json = PackageJson::from_path(package_json_path) .wrap_err("getting the package.json in current directory")?; diff --git a/crates/cli/src/cli_args/add.rs b/crates/cli/src/cli_args/add.rs index ca2ce64bb..76dab11bc 100644 --- a/crates/cli/src/cli_args/add.rs +++ b/crates/cli/src/cli_args/add.rs @@ -1,10 +1,9 @@ -use crate::state::State; +use crate::State; use clap::Args; use miette::Context; -use pacquet_npmrc::Npmrc; use pacquet_package_json::DependencyGroup; use pacquet_package_manager::Add; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; #[derive(Debug, Args)] pub struct AddDependencyOptions { @@ -58,15 +57,10 @@ pub struct AddArgs { impl AddArgs { /// Execute the subcommand. - pub async fn run(&self, package_json_path: &Path) -> miette::Result<()> { - let config = Npmrc::current().leak(); - let mut package_manager = - State::init(package_json_path, config).wrap_err("initializing the package manager")?; - + pub async fn run(&self, mut state: State) -> miette::Result<()> { // TODO: if a package already exists in another dependency group, don't remove the existing entry. - let State { config, package_json, lockfile, http_client, tarball_cache } = - &mut package_manager; + let State { config, package_json, lockfile, http_client, tarball_cache } = &mut state; Add { tarball_cache, diff --git a/crates/cli/src/cli_args/install.rs b/crates/cli/src/cli_args/install.rs index 170d282a3..b13632340 100644 --- a/crates/cli/src/cli_args/install.rs +++ b/crates/cli/src/cli_args/install.rs @@ -1,10 +1,7 @@ -use crate::state::State; +use crate::State; use clap::Args; -use miette::Context; -use pacquet_npmrc::Npmrc; use pacquet_package_json::DependencyGroup; use pacquet_package_manager::Install; -use std::path::Path; #[derive(Debug, Args)] pub struct InstallDependencyOptions { @@ -51,12 +48,8 @@ pub struct InstallArgs { } impl InstallArgs { - pub async fn run(&self, package_json_path: &Path) -> miette::Result<()> { - let config = Npmrc::current().leak(); - let package_manager = - State::init(package_json_path, config).wrap_err("initializing the package manager")?; - - let State { config, http_client, tarball_cache, lockfile, package_json } = &package_manager; + pub async fn run(&self, state: State) -> miette::Result<()> { + let State { config, http_client, tarball_cache, lockfile, package_json } = &state; let InstallArgs { dependency_options, frozen_lockfile } = self; Install { diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index b0cd27ee2..679893657 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -5,6 +5,7 @@ use clap::Parser; use cli_args::CliArgs; use miette::set_panic_hook; use pacquet_diagnostics::enable_tracing_by_env; +use state::State; pub async fn main() -> miette::Result<()> { enable_tracing_by_env(); From 509c368ae94319ef9b0034c3ab4504c4ca5e6f49 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 02:43:38 +0700 Subject: [PATCH 161/210] refactor(npmrc): dependency injection --- Cargo.lock | 1 + crates/cli/Cargo.toml | 1 + crates/cli/src/cli_args.rs | 12 +++--- crates/npmrc/src/lib.rs | 77 +++++++++++++++++++++++++------------- 4 files changed, 59 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1b707cbf0..bef96b003 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1297,6 +1297,7 @@ dependencies = [ "assert_cmd", "clap", "command-extra", + "home", "insta", "miette", "pacquet_cafs", diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 7f23e9b15..6697d3833 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -27,6 +27,7 @@ pacquet_tarball = { workspace = true } pacquet_diagnostics = { workspace = true } clap = { workspace = true } +home = { workspace = true } miette = { workspace = true } reqwest = { workspace = true } pipe-trait = { workspace = true } diff --git a/crates/cli/src/cli_args.rs b/crates/cli/src/cli_args.rs index c4430b154..c5c5a4ed5 100644 --- a/crates/cli/src/cli_args.rs +++ b/crates/cli/src/cli_args.rs @@ -12,7 +12,7 @@ use pacquet_executor::execute_shell; use pacquet_npmrc::Npmrc; use pacquet_package_json::PackageJson; use run::RunArgs; -use std::path::PathBuf; +use std::{env, path::PathBuf}; use store::StoreCommand; /// Experimental package manager for node.js written in rust. @@ -53,10 +53,8 @@ impl CliArgs { /// Execute the command pub async fn run(&self) -> miette::Result<()> { let package_json_path = self.dir.join("package.json"); - let state = || { - State::init(&package_json_path, Npmrc::current().leak()) - .wrap_err("initialize the state") - }; + let npmrc = || Npmrc::current(env::current_dir, home::home_dir, Default::default).leak(); + let state = || State::init(&package_json_path, npmrc()).wrap_err("initialize the state"); match &self.command { CliCommand::Init => { @@ -107,11 +105,11 @@ impl CliArgs { panic!("Not implemented") } StoreCommand::Prune => { - let config = Npmrc::current().leak(); + let config = npmrc(); pacquet_cafs::prune_sync(&config.store_dir).wrap_err("pruning store")?; } StoreCommand::Path => { - let config = Npmrc::current().leak(); + let config = npmrc(); println!("{}", config.store_dir.display()); } }, diff --git a/crates/npmrc/src/lib.rs b/crates/npmrc/src/lib.rs index c4b797f99..3c5fc0bf8 100644 --- a/crates/npmrc/src/lib.rs +++ b/crates/npmrc/src/lib.rs @@ -2,7 +2,7 @@ mod custom_deserializer; use pipe_trait::Pipe; use serde::Deserialize; -use std::{env, fs, path::PathBuf}; +use std::{fs, path::PathBuf}; use crate::custom_deserializer::{ bool_true, default_hoist_pattern, default_modules_cache_max_age, default_modules_dir, @@ -160,13 +160,23 @@ impl Npmrc { /// Try loading `.npmrc` in the current directory. /// If fails, try in the home directory. /// If fails again, return the default. - pub fn current() -> Self { - let path = match env::current_dir() { + pub fn current( + current_dir: CurrentDir, + home_dir: HomeDir, + default: Default, + ) -> Self + where + CurrentDir: FnOnce() -> Result, + HomeDir: FnOnce() -> Option, + Default: FnOnce() -> Npmrc, + { + let path = match current_dir() { Ok(dir) => Some(dir.join(".npmrc")), - _ => home::home_dir().map(|dir| dir.join(".npmrc")), + _ => home_dir().map(|dir| dir.join(".npmrc")), }; if let Some(file) = path { + // TODO: should it throw error instead? if let Ok(content) = fs::read_to_string(file) { if let Ok(npmrc) = serde_ini::from_str(&content) { return npmrc; @@ -174,7 +184,7 @@ impl Npmrc { } } - Npmrc::default() + default() } /// Persist the config data until the program terminates. @@ -191,7 +201,7 @@ impl Default for Npmrc { #[cfg(test)] mod tests { - use std::{env, io::Write, str::FromStr}; + use std::{env, str::FromStr}; use pretty_assertions::assert_eq; use tempfile::tempdir; @@ -250,12 +260,6 @@ mod tests { env::remove_var("XDG_DATA_HOME"); } - #[test] - pub fn should_return_npmrc() { - let value = Npmrc::current(); - assert!(value.symlink); - } - #[test] pub fn should_use_relative_virtual_store_dir() { let value: Npmrc = serde_ini::from_str("virtual-store-dir=node_modules/.pacquet").unwrap(); @@ -284,25 +288,48 @@ mod tests { #[test] pub fn test_current_folder_for_npmrc() { let tmp = tempdir().unwrap(); - let current_directory = env::current_dir().unwrap(); - let mut f = fs::File::create(tmp.path().join(".npmrc")).expect("Unable to create file"); - f.write_all(b"symlink=false").unwrap(); - env::set_current_dir(tmp.path()).unwrap(); - let config = Npmrc::current(); + fs::write(tmp.path().join(".npmrc"), "symlink=false").expect("write to .npmrc"); + let config = Npmrc::current( + || tmp.path().to_path_buf().pipe(Ok::<_, ()>), + || unreachable!("shouldn't reach home dir"), + || unreachable!("shouldn't reach default"), + ); assert!(!config.symlink); - env::set_current_dir(current_directory).unwrap(); } #[test] pub fn test_current_folder_for_invalid_npmrc() { let tmp = tempdir().unwrap(); - let current_directory = env::current_dir().unwrap(); - let mut f = fs::File::create(tmp.path().join(".npmrc")).expect("Unable to create file"); // write invalid utf-8 value to npmrc - f.write_all(b"Hello \xff World").unwrap(); - env::set_current_dir(tmp.path()).unwrap(); - let config = Npmrc::current(); - assert!(config.symlink); - env::set_current_dir(current_directory).unwrap(); + fs::write(tmp.path().join(".npmrc"), b"Hello \xff World").expect("write to .npmrc"); + let config = + Npmrc::current(|| tmp.path().to_path_buf().pipe(Ok::<_, ()>), || None, Npmrc::new); + assert!(config.symlink); // TODO: what the hell? why succeed? + } + + #[test] + pub fn test_current_folder_fallback_to_home() { + let current_dir = tempdir().unwrap(); + let home_dir = tempdir().unwrap(); + dbg!(¤t_dir, &home_dir); + fs::write(home_dir.path().join(".npmrc"), "symlink=false").expect("write to .npmrc"); + let config = Npmrc::current( + || current_dir.path().to_path_buf().pipe(Ok::<_, ()>), + || home_dir.path().to_path_buf().pipe(Some), + || unreachable!("shouldn't reach home dir"), + ); + assert!(!config.symlink); + } + + #[test] + pub fn test_current_folder_fallback_to_default() { + let current_dir = tempdir().unwrap(); + let home_dir = tempdir().unwrap(); + let config = Npmrc::current( + || current_dir.path().to_path_buf().pipe(Ok::<_, ()>), + || home_dir.path().to_path_buf().pipe(Some), + || serde_ini::from_str("symlink=false").unwrap(), + ); + assert!(!config.symlink); } } From 45e802c9a8a171ac51a2799242af7e04372b9d9f Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 02:48:03 +0700 Subject: [PATCH 162/210] docs: what's wrong --- crates/npmrc/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/npmrc/src/lib.rs b/crates/npmrc/src/lib.rs index 3c5fc0bf8..0d5202eb9 100644 --- a/crates/npmrc/src/lib.rs +++ b/crates/npmrc/src/lib.rs @@ -170,6 +170,9 @@ impl Npmrc { HomeDir: FnOnce() -> Option, Default: FnOnce() -> Npmrc, { + // TODO: this code makes no sense. + // TODO: it should have merged the settings. + let path = match current_dir() { Ok(dir) => Some(dir.join(".npmrc")), _ => home_dir().map(|dir| dir.join(".npmrc")), From ce0369a21d8c7f4c7a4ad3964b3c528773e64bb0 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 02:59:11 +0700 Subject: [PATCH 163/210] fix(npmrc): the algorithm still makes no sense --- crates/npmrc/src/lib.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/crates/npmrc/src/lib.rs b/crates/npmrc/src/lib.rs index 0d5202eb9..d7e9323ea 100644 --- a/crates/npmrc/src/lib.rs +++ b/crates/npmrc/src/lib.rs @@ -173,21 +173,19 @@ impl Npmrc { // TODO: this code makes no sense. // TODO: it should have merged the settings. - let path = match current_dir() { - Ok(dir) => Some(dir.join(".npmrc")), - _ => home_dir().map(|dir| dir.join(".npmrc")), + let load = |dir: PathBuf| -> Option { + dir.join(".npmrc") + .pipe(fs::read_to_string) + .ok()? // TODO: should it throw error instead? + .pipe_as_ref(serde_ini::from_str) + .ok() // TODO: should it throw error instead? }; - if let Some(file) = path { - // TODO: should it throw error instead? - if let Ok(content) = fs::read_to_string(file) { - if let Ok(npmrc) = serde_ini::from_str(&content) { - return npmrc; - } - } - } - - default() + current_dir() + .ok() + .and_then(load) + .or_else(|| home_dir().and_then(load)) + .unwrap_or_else(default) } /// Persist the config data until the program terminates. From 636229b09c572da70c49573110d030332987c1cb Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 13:51:31 +0700 Subject: [PATCH 164/210] style: move error type closer to its user --- crates/cli/src/state.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/cli/src/state.rs b/crates/cli/src/state.rs index 58039c92a..659f9ee55 100644 --- a/crates/cli/src/state.rs +++ b/crates/cli/src/state.rs @@ -8,6 +8,14 @@ use reqwest::Client; use std::path::PathBuf; use thiserror::Error; +pub struct State { + pub config: &'static Npmrc, + pub package_json: PackageJson, + pub lockfile: Option, + pub http_client: Client, + pub tarball_cache: Cache, +} + #[derive(Error, Debug, Diagnostic)] #[non_exhaustive] pub enum InitStateError { @@ -20,14 +28,6 @@ pub enum InitStateError { LoadLockfile(LoadLockfileError), } -pub struct State { - pub config: &'static Npmrc, - pub package_json: PackageJson, - pub lockfile: Option, - pub http_client: Client, - pub tarball_cache: Cache, -} - impl State { pub fn init>( package_json_path: P, From fce56730c43e8a9616a826a1f9829884e8b8e421 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 14:07:04 +0700 Subject: [PATCH 165/210] refactor: use derive_more --- Cargo.lock | 2 +- crates/cli/Cargo.toml | 16 ++++++++-------- crates/cli/src/state.rs | 10 ++++------ 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bef96b003..3d66b0495 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1297,6 +1297,7 @@ dependencies = [ "assert_cmd", "clap", "command-extra", + "derive_more", "home", "insta", "miette", @@ -1316,7 +1317,6 @@ dependencies = [ "reqwest", "serde_json", "tempfile", - "thiserror", "tokio", "tracing", ] diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 6697d3833..3de91f268 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -26,14 +26,14 @@ pacquet_registry = { workspace = true } pacquet_tarball = { workspace = true } pacquet_diagnostics = { workspace = true } -clap = { workspace = true } -home = { workspace = true } -miette = { workspace = true } -reqwest = { workspace = true } -pipe-trait = { workspace = true } -thiserror = { workspace = true } -tokio = { workspace = true } -tracing = { workspace = true } +clap = { workspace = true } +derive_more = { workspace = true } +home = { workspace = true } +miette = { workspace = true } +reqwest = { workspace = true } +pipe-trait = { workspace = true } +tokio = { workspace = true } +tracing = { workspace = true } [dev-dependencies] pacquet_testing_utils = { workspace = true } diff --git a/crates/cli/src/state.rs b/crates/cli/src/state.rs index 659f9ee55..df8c09520 100644 --- a/crates/cli/src/state.rs +++ b/crates/cli/src/state.rs @@ -1,3 +1,4 @@ +use derive_more::{Display, Error}; use miette::Diagnostic; use pacquet_lockfile::{LoadLockfileError, Lockfile}; use pacquet_npmrc::Npmrc; @@ -6,7 +7,6 @@ use pacquet_tarball::Cache; use pipe_trait::Pipe; use reqwest::Client; use std::path::PathBuf; -use thiserror::Error; pub struct State { pub config: &'static Npmrc, @@ -16,16 +16,14 @@ pub struct State { pub tarball_cache: Cache, } -#[derive(Error, Debug, Diagnostic)] +#[derive(Debug, Display, Error, Diagnostic)] #[non_exhaustive] pub enum InitStateError { - #[error(transparent)] #[diagnostic(transparent)] - LoadPackageJson(PackageJsonError), + LoadPackageJson(#[error(source)] PackageJsonError), - #[error(transparent)] #[diagnostic(transparent)] - LoadLockfile(LoadLockfileError), + LoadLockfile(#[error(source)] LoadLockfileError), } impl State { From 1b1a760145f1f7945a387363e4cf23ebea54ec82 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 14:38:30 +0700 Subject: [PATCH 166/210] refactor(cli): lazy package_json_path --- crates/cli/src/cli_args.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/cli/src/cli_args.rs b/crates/cli/src/cli_args.rs index c5c5a4ed5..73429e9f2 100644 --- a/crates/cli/src/cli_args.rs +++ b/crates/cli/src/cli_args.rs @@ -52,19 +52,19 @@ pub enum CliCommand { impl CliArgs { /// Execute the command pub async fn run(&self) -> miette::Result<()> { - let package_json_path = self.dir.join("package.json"); + let package_json_path = || self.dir.join("package.json"); let npmrc = || Npmrc::current(env::current_dir, home::home_dir, Default::default).leak(); - let state = || State::init(&package_json_path, npmrc()).wrap_err("initialize the state"); + let state = || State::init(package_json_path(), npmrc()).wrap_err("initialize the state"); match &self.command { CliCommand::Init => { // init command throws an error if package.json file exist. - PackageJson::init(&package_json_path).wrap_err("initialize package.json")?; + PackageJson::init(&package_json_path()).wrap_err("initialize package.json")?; } CliCommand::Add(args) => return args.run(state()?).await, CliCommand::Install(args) => return args.run(state()?).await, CliCommand::Test => { - let package_json = PackageJson::from_path(package_json_path) + let package_json = PackageJson::from_path(package_json_path()) .wrap_err("getting the package.json in current directory")?; if let Some(script) = package_json.script("test", false)? { execute_shell(script) @@ -72,7 +72,7 @@ impl CliArgs { } } CliCommand::Run(args) => { - let package_json = PackageJson::from_path(package_json_path) + let package_json = PackageJson::from_path(package_json_path()) .wrap_err("getting the package.json in current directory")?; if let Some(script) = package_json.script(&args.command, args.if_present)? { let mut command = script.to_string(); @@ -88,7 +88,7 @@ impl CliArgs { // object. If no start property is specified on the scripts object, it will attempt to // run node server.js as a default, failing if neither are present. // The intended usage of the property is to specify a command that starts your program. - let package_json = PackageJson::from_path(package_json_path) + let package_json = PackageJson::from_path(package_json_path()) .wrap_err("getting the package.json in current directory")?; let command = if let Some(script) = package_json.script("start", true)? { script From ce93200797f0962402873e92226c5a1a55364cfa Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 14:39:34 +0700 Subject: [PATCH 167/210] refactor: be explicit --- crates/cli/src/state.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/cli/src/state.rs b/crates/cli/src/state.rs index df8c09520..b2507e547 100644 --- a/crates/cli/src/state.rs +++ b/crates/cli/src/state.rs @@ -27,14 +27,13 @@ pub enum InitStateError { } impl State { - pub fn init>( - package_json_path: P, + pub fn init( + package_json_path: PathBuf, config: &'static Npmrc, ) -> Result { Ok(State { config, package_json: package_json_path - .into() .pipe(PackageJson::create_if_needed) .map_err(InitStateError::LoadPackageJson)?, lockfile: call_load_lockfile(config.lockfile, Lockfile::load_from_current_dir) From 28d3695a3ea98efca3171d3a6baec5a311237d66 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 14:52:23 +0700 Subject: [PATCH 168/210] refactor: destroy args on use --- crates/cli/src/cli_args.rs | 7 ++++--- crates/cli/src/cli_args/add.rs | 2 +- crates/cli/src/cli_args/install.rs | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/crates/cli/src/cli_args.rs b/crates/cli/src/cli_args.rs index 73429e9f2..c0bc48659 100644 --- a/crates/cli/src/cli_args.rs +++ b/crates/cli/src/cli_args.rs @@ -51,12 +51,13 @@ pub enum CliCommand { impl CliArgs { /// Execute the command - pub async fn run(&self) -> miette::Result<()> { - let package_json_path = || self.dir.join("package.json"); + pub async fn run(self) -> miette::Result<()> { + let CliArgs { command, dir } = self; + let package_json_path = || dir.join("package.json"); let npmrc = || Npmrc::current(env::current_dir, home::home_dir, Default::default).leak(); let state = || State::init(package_json_path(), npmrc()).wrap_err("initialize the state"); - match &self.command { + match command { CliCommand::Init => { // init command throws an error if package.json file exist. PackageJson::init(&package_json_path()).wrap_err("initialize package.json")?; diff --git a/crates/cli/src/cli_args/add.rs b/crates/cli/src/cli_args/add.rs index 76dab11bc..2a4da1d76 100644 --- a/crates/cli/src/cli_args/add.rs +++ b/crates/cli/src/cli_args/add.rs @@ -57,7 +57,7 @@ pub struct AddArgs { impl AddArgs { /// Execute the subcommand. - pub async fn run(&self, mut state: State) -> miette::Result<()> { + pub async fn run(self, mut state: State) -> miette::Result<()> { // TODO: if a package already exists in another dependency group, don't remove the existing entry. let State { config, package_json, lockfile, http_client, tarball_cache } = &mut state; diff --git a/crates/cli/src/cli_args/install.rs b/crates/cli/src/cli_args/install.rs index b13632340..763e272db 100644 --- a/crates/cli/src/cli_args/install.rs +++ b/crates/cli/src/cli_args/install.rs @@ -48,7 +48,7 @@ pub struct InstallArgs { } impl InstallArgs { - pub async fn run(&self, state: State) -> miette::Result<()> { + pub async fn run(self, state: State) -> miette::Result<()> { let State { config, http_client, tarball_cache, lockfile, package_json } = &state; let InstallArgs { dependency_options, frozen_lockfile } = self; @@ -59,7 +59,7 @@ impl InstallArgs { package_json, lockfile: lockfile.as_ref(), dependency_groups: dependency_options.dependency_groups(), - frozen_lockfile: *frozen_lockfile, + frozen_lockfile, } .run() .await; From 0a91d1ec9f2b2df35510a8889ce2734c0d5f39bb Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 14:53:34 +0700 Subject: [PATCH 169/210] refactor: remove early return --- crates/cli/src/cli_args.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/cli/src/cli_args.rs b/crates/cli/src/cli_args.rs index c0bc48659..94ff37b44 100644 --- a/crates/cli/src/cli_args.rs +++ b/crates/cli/src/cli_args.rs @@ -62,8 +62,8 @@ impl CliArgs { // init command throws an error if package.json file exist. PackageJson::init(&package_json_path()).wrap_err("initialize package.json")?; } - CliCommand::Add(args) => return args.run(state()?).await, - CliCommand::Install(args) => return args.run(state()?).await, + CliCommand::Add(args) => args.run(state()?).await?, + CliCommand::Install(args) => args.run(state()?).await?, CliCommand::Test => { let package_json = PackageJson::from_path(package_json_path()) .wrap_err("getting the package.json in current directory")?; From 206a8b713de2c5d0a426aa6f7d7d79831d0e1d13 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 15:07:06 +0700 Subject: [PATCH 170/210] refactor(cli): attach code to args --- crates/cli/src/cli_args.rs | 30 ++---------------------------- crates/cli/src/cli_args/run.rs | 25 +++++++++++++++++++++++++ crates/cli/src/cli_args/store.rs | 24 ++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 28 deletions(-) diff --git a/crates/cli/src/cli_args.rs b/crates/cli/src/cli_args.rs index 94ff37b44..9ec4e89db 100644 --- a/crates/cli/src/cli_args.rs +++ b/crates/cli/src/cli_args.rs @@ -72,18 +72,7 @@ impl CliArgs { .wrap_err(format!("executing command: \"{0}\"", script))?; } } - CliCommand::Run(args) => { - let package_json = PackageJson::from_path(package_json_path()) - .wrap_err("getting the package.json in current directory")?; - if let Some(script) = package_json.script(&args.command, args.if_present)? { - let mut command = script.to_string(); - // append an empty space between script and additional args - command.push(' '); - // then append the additional args - command.push_str(&args.args.join(" ")); - execute_shell(command.trim())?; - } - } + CliCommand::Run(args) => args.run(package_json_path())?, CliCommand::Start => { // Runs an arbitrary command specified in the package's start property of its scripts // object. If no start property is specified on the scripts object, it will attempt to @@ -98,22 +87,7 @@ impl CliArgs { }; execute_shell(command).wrap_err(format!("executing command: \"{0}\"", command))?; } - CliCommand::Store(command) => match command { - StoreCommand::Store => { - panic!("Not implemented") - } - StoreCommand::Add => { - panic!("Not implemented") - } - StoreCommand::Prune => { - let config = npmrc(); - pacquet_cafs::prune_sync(&config.store_dir).wrap_err("pruning store")?; - } - StoreCommand::Path => { - let config = npmrc(); - println!("{}", config.store_dir.display()); - } - }, + CliCommand::Store(command) => command.run(|| npmrc())?, } Ok(()) diff --git a/crates/cli/src/cli_args/run.rs b/crates/cli/src/cli_args/run.rs index 378179aa5..817051f77 100644 --- a/crates/cli/src/cli_args/run.rs +++ b/crates/cli/src/cli_args/run.rs @@ -1,4 +1,8 @@ use clap::Args; +use miette::Context; +use pacquet_executor::execute_shell; +use pacquet_package_json::PackageJson; +use std::path::PathBuf; #[derive(Debug, Args)] pub struct RunArgs { @@ -14,3 +18,24 @@ pub struct RunArgs { #[clap(long)] pub if_present: bool, } + +impl RunArgs { + /// Execute the subcommand. + pub fn run(self, package_json_path: PathBuf) -> miette::Result<()> { + let RunArgs { command, args, if_present } = self; + + let package_json = PackageJson::from_path(package_json_path) + .wrap_err("getting the package.json in current directory")?; + + if let Some(script) = package_json.script(&command, if_present)? { + let mut command = script.to_string(); + // append an empty space between script and additional args + command.push(' '); + // then append the additional args + command.push_str(&args.join(" ")); + execute_shell(command.trim())?; + } + + Ok(()) + } +} diff --git a/crates/cli/src/cli_args/store.rs b/crates/cli/src/cli_args/store.rs index 26492bff5..4a908fe41 100644 --- a/crates/cli/src/cli_args/store.rs +++ b/crates/cli/src/cli_args/store.rs @@ -1,4 +1,6 @@ use clap::Subcommand; +use miette::Context; +use pacquet_npmrc::Npmrc; #[derive(Debug, Subcommand)] pub enum StoreCommand { @@ -15,3 +17,25 @@ pub enum StoreCommand { /// Returns the path to the active store directory. Path, } + +impl StoreCommand { + /// Execute the subcommand. + pub fn run<'a>(self, config: impl FnOnce() -> &'a Npmrc) -> miette::Result<()> { + match self { + StoreCommand::Store => { + panic!("Not implemented") + } + StoreCommand::Add => { + panic!("Not implemented") + } + StoreCommand::Prune => { + pacquet_cafs::prune_sync(&config().store_dir).wrap_err("pruning store")?; + } + StoreCommand::Path => { + println!("{}", config().store_dir.display()); + } + } + + Ok(()) + } +} From f89a5f9db9f89a0c2175e4626cfb73d37abe81f1 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 15:09:00 +0700 Subject: [PATCH 171/210] docs(cli): State --- crates/cli/src/state.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/cli/src/state.rs b/crates/cli/src/state.rs index b2507e547..a0590bf4a 100644 --- a/crates/cli/src/state.rs +++ b/crates/cli/src/state.rs @@ -8,6 +8,7 @@ use pipe_trait::Pipe; use reqwest::Client; use std::path::PathBuf; +/// Application state when running `pacquet run` or `pacquet install`. pub struct State { pub config: &'static Npmrc, pub package_json: PackageJson, @@ -16,6 +17,7 @@ pub struct State { pub tarball_cache: Cache, } +/// Error type of [`State::init`]. #[derive(Debug, Display, Error, Diagnostic)] #[non_exhaustive] pub enum InitStateError { @@ -27,6 +29,7 @@ pub enum InitStateError { } impl State { + /// Initialize the application state. pub fn init( package_json_path: PathBuf, config: &'static Npmrc, From d5dc1660e319a2c586416987749b60560d604b00 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 18:48:58 +0700 Subject: [PATCH 172/210] docs: fields of State --- crates/cli/src/state.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/cli/src/state.rs b/crates/cli/src/state.rs index a0590bf4a..6c6f09a1b 100644 --- a/crates/cli/src/state.rs +++ b/crates/cli/src/state.rs @@ -10,10 +10,15 @@ use std::path::PathBuf; /// Application state when running `pacquet run` or `pacquet install`. pub struct State { + /// Configuration read from `.npmrc` pub config: &'static Npmrc, + /// Data from the `package.json` file. pub package_json: PackageJson, + /// Data from the `pnpm-lock.yaml` file. pub lockfile: Option, + /// HTTP client to make HTTP requests. pub http_client: Client, + /// Shared cache that store downloaded tarballs. pub tarball_cache: Cache, } From bc73b259cfbab2bdc16ebcb8bb13c20d1eb260c0 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 18:50:44 +0700 Subject: [PATCH 173/210] style: rearrange the fields --- crates/cli/src/cli_args/add.rs | 2 +- crates/cli/src/cli_args/install.rs | 2 +- crates/cli/src/state.rs | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/cli/src/cli_args/add.rs b/crates/cli/src/cli_args/add.rs index 2a4da1d76..498e354bc 100644 --- a/crates/cli/src/cli_args/add.rs +++ b/crates/cli/src/cli_args/add.rs @@ -60,7 +60,7 @@ impl AddArgs { pub async fn run(self, mut state: State) -> miette::Result<()> { // TODO: if a package already exists in another dependency group, don't remove the existing entry. - let State { config, package_json, lockfile, http_client, tarball_cache } = &mut state; + let State { tarball_cache, http_client, config, package_json, lockfile } = &mut state; Add { tarball_cache, diff --git a/crates/cli/src/cli_args/install.rs b/crates/cli/src/cli_args/install.rs index 763e272db..ab9b2a879 100644 --- a/crates/cli/src/cli_args/install.rs +++ b/crates/cli/src/cli_args/install.rs @@ -49,7 +49,7 @@ pub struct InstallArgs { impl InstallArgs { pub async fn run(self, state: State) -> miette::Result<()> { - let State { config, http_client, tarball_cache, lockfile, package_json } = &state; + let State { tarball_cache, http_client, config, package_json, lockfile } = &state; let InstallArgs { dependency_options, frozen_lockfile } = self; Install { diff --git a/crates/cli/src/state.rs b/crates/cli/src/state.rs index 6c6f09a1b..13972f9c3 100644 --- a/crates/cli/src/state.rs +++ b/crates/cli/src/state.rs @@ -10,16 +10,16 @@ use std::path::PathBuf; /// Application state when running `pacquet run` or `pacquet install`. pub struct State { + /// Shared cache that store downloaded tarballs. + pub tarball_cache: Cache, + /// HTTP client to make HTTP requests. + pub http_client: Client, /// Configuration read from `.npmrc` pub config: &'static Npmrc, /// Data from the `package.json` file. pub package_json: PackageJson, /// Data from the `pnpm-lock.yaml` file. pub lockfile: Option, - /// HTTP client to make HTTP requests. - pub http_client: Client, - /// Shared cache that store downloaded tarballs. - pub tarball_cache: Cache, } /// Error type of [`State::init`]. From 3e6e49b98012d5c1a379a1af6af1d6a99f435cda Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 20:24:33 +0700 Subject: [PATCH 174/210] refactor: convert a function to a struct --- .../src/install_package_by_snapshot.rs | 15 +- .../src/install_package_from_registry.rs | 19 +- crates/tarball/src/lib.rs | 257 +++++++++--------- tasks/micro-benchmark/src/main.rs | 18 +- 4 files changed, 160 insertions(+), 149 deletions(-) diff --git a/crates/package_manager/src/install_package_by_snapshot.rs b/crates/package_manager/src/install_package_by_snapshot.rs index 0780a8b6d..d5b166c60 100644 --- a/crates/package_manager/src/install_package_by_snapshot.rs +++ b/crates/package_manager/src/install_package_by_snapshot.rs @@ -3,7 +3,7 @@ use derive_more::{Display, Error}; use miette::Diagnostic; use pacquet_lockfile::{DependencyPath, LockfileResolution, PackageSnapshot, PkgNameVerPeer}; use pacquet_npmrc::Npmrc; -use pacquet_tarball::{download_tarball_to_store, Cache, TarballError}; +use pacquet_tarball::{Cache, DownloadTarballToStore, TarballError}; use pipe_trait::Pipe; use reqwest::Client; use std::borrow::Cow; @@ -68,14 +68,15 @@ impl<'a> InstallPackageBySnapshot<'a> { }; // TODO: skip when already exists in store? - let cas_paths = download_tarball_to_store( + let cas_paths = DownloadTarballToStore { tarball_cache, http_client, - &config.store_dir, - integrity, - None, - &tarball_url, - ) + store_dir: &config.store_dir, + package_integrity: integrity, + package_unpacked_size: None, + package_url: &tarball_url, + } + .run() .await .map_err(InstallPackageBySnapshotError::DownloadTarball)?; diff --git a/crates/package_manager/src/install_package_from_registry.rs b/crates/package_manager/src/install_package_from_registry.rs index 1e0613273..45706d5d2 100644 --- a/crates/package_manager/src/install_package_from_registry.rs +++ b/crates/package_manager/src/install_package_from_registry.rs @@ -3,7 +3,7 @@ use derive_more::{Display, Error}; use miette::Diagnostic; use pacquet_npmrc::Npmrc; use pacquet_registry::{Package, PackageTag, PackageVersion, RegistryError}; -use pacquet_tarball::{download_tarball_to_store, Cache, TarballError}; +use pacquet_tarball::{Cache, DownloadTarballToStore, TarballError}; use reqwest::Client; use std::{path::Path, str::FromStr}; @@ -80,14 +80,19 @@ impl<'a> InstallPackageFromRegistry<'a> { let store_folder_name = package_version.to_virtual_store_name(); // TODO: skip when it already exists in store? - let cas_paths = download_tarball_to_store( + let cas_paths = DownloadTarballToStore { tarball_cache, http_client, - &config.store_dir, - package_version.dist.integrity.as_ref().expect("has integrity field"), - package_version.dist.unpacked_size, - package_version.as_tarball_url(), - ) + store_dir: &config.store_dir, + package_integrity: package_version + .dist + .integrity + .as_ref() + .expect("has integrity field"), + package_unpacked_size: package_version.dist.unpacked_size, + package_url: package_version.as_tarball_url(), + } + .run() .await .map_err(InstallPackageFromRegistryError::DownloadTarballToStore)?; diff --git a/crates/tarball/src/lib.rs b/crates/tarball/src/lib.rs index a6feeac45..7af169c68 100644 --- a/crates/tarball/src/lib.rs +++ b/crates/tarball/src/lib.rs @@ -110,126 +110,129 @@ fn verify_checksum(data: &[u8], integrity: Integrity) -> Result, - package_url: &str, -) -> Result>, TarballError> { - // QUESTION: I see no copying from existing store_dir, is there such mechanism? - // TODO: If it's not implemented yet, implement it - - if let Some(cache_lock) = cache.get(package_url) { - let notify = match &*cache_lock.write().await { - CacheValue::Available(cas_paths) => { +#[must_use] +pub struct DownloadTarballToStore<'a> { + pub tarball_cache: &'a Cache, + pub http_client: &'a Client, + pub store_dir: &'static Path, + pub package_integrity: &'a str, + pub package_unpacked_size: Option, + pub package_url: &'a str, +} + +impl<'a> DownloadTarballToStore<'a> { + pub async fn run(self) -> Result>, TarballError> { + let &DownloadTarballToStore { tarball_cache, package_url, .. } = &self; + + // QUESTION: I see no copying from existing store_dir, is there such mechanism? + // TODO: If it's not implemented yet, implement it + + if let Some(cache_lock) = tarball_cache.get(package_url) { + let notify = match &*cache_lock.write().await { + CacheValue::Available(cas_paths) => { + return Ok(Arc::clone(cas_paths)); + } + CacheValue::InProgress(notify) => Arc::clone(notify), + }; + + tracing::info!(target: "pacquet::download", ?package_url, "Wait for cache"); + notify.notified().await; + if let CacheValue::Available(cas_paths) = &*cache_lock.read().await { return Ok(Arc::clone(cas_paths)); } - CacheValue::InProgress(notify) => Arc::clone(notify), - }; - - tracing::info!(target: "pacquet::download", ?package_url, "Wait for cache"); - notify.notified().await; - if let CacheValue::Available(cas_paths) = &*cache_lock.read().await { - return Ok(Arc::clone(cas_paths)); - } - unreachable!("Failed to get or compute tarball data for {package_url:?}"); - } else { - let notify = Arc::new(Notify::new()); - let cache_lock = notify - .pipe_ref(Arc::clone) - .pipe(CacheValue::InProgress) - .pipe(RwLock::new) - .pipe(Arc::new); - if cache.insert(package_url.to_string(), Arc::clone(&cache_lock)).is_some() { - tracing::warn!(target: "pacquet::download", ?package_url, "Race condition detected when writing to cache"); + unreachable!("Failed to get or compute tarball data for {package_url:?}"); + } else { + let notify = Arc::new(Notify::new()); + let cache_lock = notify + .pipe_ref(Arc::clone) + .pipe(CacheValue::InProgress) + .pipe(RwLock::new) + .pipe(Arc::new); + if tarball_cache.insert(package_url.to_string(), Arc::clone(&cache_lock)).is_some() { + tracing::warn!(target: "pacquet::download", ?package_url, "Race condition detected when writing to cache"); + } + let cas_paths = self.without_cache().await?; + let mut cache_write = cache_lock.write().await; + *cache_write = CacheValue::Available(Arc::clone(&cas_paths)); + notify.notify_waiters(); + Ok(cas_paths) } - let cas_paths = download_tarball_to_store_uncached( - package_url, + } + + async fn without_cache(&self) -> Result>, TarballError> { + let &DownloadTarballToStore { http_client, store_dir, package_integrity, package_unpacked_size, - ) - .await?; - let mut cache_write = cache_lock.write().await; - *cache_write = CacheValue::Available(Arc::clone(&cas_paths)); - notify.notify_waiters(); - Ok(cas_paths) - } -} - -async fn download_tarball_to_store_uncached( - package_url: &str, - http_client: &Client, - store_dir: &'static Path, - package_integrity: &str, - package_unpacked_size: Option, -) -> Result>, TarballError> { - tracing::info!(target: "pacquet::download", ?package_url, "New cache"); - - let network_error = |error| NetworkError { url: package_url.to_string(), error }; - let response = http_client - .get(package_url) - .send() - .await - .map_err(network_error)? - .bytes() - .await - .map_err(network_error)?; - - tracing::info!(target: "pacquet::download", ?package_url, "Download completed"); - - let package_integrity: Integrity = - package_integrity.parse().map_err(|error| ParseIntegrityError { - url: package_url.to_string(), - integrity: package_integrity.to_string(), - error, - })?; - enum TaskError { - Checksum(ssri::Error), - Other(TarballError), - } - let cas_paths = tokio::task::spawn(async move { - verify_checksum(&response, package_integrity).map_err(TaskError::Checksum)?; - let data = decompress_gzip(&response, package_unpacked_size).map_err(TaskError::Other)?; - Archive::new(Cursor::new(data)) - .entries() - .map_err(TarballError::Io) - .map_err(TaskError::Other)? - .filter(|entry| !entry.as_ref().unwrap().header().entry_type().is_dir()) - .map(|entry| -> Result<(OsString, PathBuf), TarballError> { - let mut entry = entry.unwrap(); - - // Read the contents of the entry - let mut buffer = Vec::with_capacity(entry.size() as usize); - entry.read_to_end(&mut buffer).unwrap(); - - let entry_path = entry.path().unwrap(); - let cleaned_entry_path = - entry_path.components().skip(1).collect::().into_os_string(); - let integrity = pacquet_cafs::write_sync(store_dir, &buffer)?; - - Ok((cleaned_entry_path, store_dir.join(integrity))) - }) - .collect::, TarballError>>() - .map_err(TaskError::Other) - }) - .await - .expect("no join error") - .map_err(|error| match error { - TaskError::Checksum(error) => { - TarballError::Checksum(VerifyChecksumError { url: package_url.to_string(), error }) + package_url, + .. + } = self; + + tracing::info!(target: "pacquet::download", ?package_url, "New cache"); + + let network_error = |error| NetworkError { url: package_url.to_string(), error }; + let response = http_client + .get(package_url) + .send() + .await + .map_err(network_error)? + .bytes() + .await + .map_err(network_error)?; + + tracing::info!(target: "pacquet::download", ?package_url, "Download completed"); + + let package_integrity: Integrity = + package_integrity.parse().map_err(|error| ParseIntegrityError { + url: package_url.to_string(), + integrity: package_integrity.to_string(), + error, + })?; + enum TaskError { + Checksum(ssri::Error), + Other(TarballError), } - TaskError::Other(error) => error, - })? - .pipe(Arc::new); + let cas_paths = tokio::task::spawn(async move { + verify_checksum(&response, package_integrity).map_err(TaskError::Checksum)?; + let data = + decompress_gzip(&response, package_unpacked_size).map_err(TaskError::Other)?; + Archive::new(Cursor::new(data)) + .entries() + .map_err(TarballError::Io) + .map_err(TaskError::Other)? + .filter(|entry| !entry.as_ref().unwrap().header().entry_type().is_dir()) + .map(|entry| -> Result<(OsString, PathBuf), TarballError> { + let mut entry = entry.unwrap(); + + // Read the contents of the entry + let mut buffer = Vec::with_capacity(entry.size() as usize); + entry.read_to_end(&mut buffer).unwrap(); + + let entry_path = entry.path().unwrap(); + let cleaned_entry_path = + entry_path.components().skip(1).collect::().into_os_string(); + let integrity = pacquet_cafs::write_sync(store_dir, &buffer)?; + + Ok((cleaned_entry_path, store_dir.join(integrity))) + }) + .collect::, TarballError>>() + .map_err(TaskError::Other) + }) + .await + .expect("no join error") + .map_err(|error| match error { + TaskError::Checksum(error) => { + TarballError::Checksum(VerifyChecksumError { url: package_url.to_string(), error }) + } + TaskError::Other(error) => error, + })? + .pipe(Arc::new); - tracing::info!(target: "pacquet::download", ?package_url, "Checksum verified"); + tracing::info!(target: "pacquet::download", ?package_url, "Checksum verified"); - Ok(cas_paths) + Ok(cas_paths) + } } #[cfg(test)] @@ -260,14 +263,15 @@ mod tests { #[cfg(not(target_os = "windows"))] async fn packages_under_orgs_should_work() { let (store_dir, store_path) = tempdir_with_leaked_path(); - let cas_files = download_tarball_to_store( - &Default::default(), - &Client::new(), - store_path, - "sha512-dj7vjIn1Ar8sVXj2yAXiMNCJDmS9MQ9XMlIecX2dIzzhjSHCyKo4DdXjXMs7wKW2kj6yvVRSpuQjOZ3YLrh56w==", - Some(16697), - "https://registry.npmjs.org/@fastify/error/-/error-3.3.0.tgz", - ) + let cas_files = DownloadTarballToStore { + tarball_cache: &Default::default(), + http_client: &Default::default(), + store_dir: store_path, + package_integrity: "sha512-dj7vjIn1Ar8sVXj2yAXiMNCJDmS9MQ9XMlIecX2dIzzhjSHCyKo4DdXjXMs7wKW2kj6yvVRSpuQjOZ3YLrh56w==", + package_unpacked_size: Some(16697), + package_url: "https://registry.npmjs.org/@fastify/error/-/error-3.3.0.tgz" + } + .run() .await .unwrap(); @@ -299,14 +303,15 @@ mod tests { #[tokio::test] async fn should_throw_error_on_checksum_mismatch() { let (store_dir, store_path) = tempdir_with_leaked_path(); - download_tarball_to_store( - &Default::default(), - &Client::new(), - store_path, - "sha512-aaaan1Ar8sVXj2yAXiMNCJDmS9MQ9XMlIecX2dIzzhjSHCyKo4DdXjXMs7wKW2kj6yvVRSpuQjOZ3YLrh56w==", - Some(16697), - "https://registry.npmjs.org/@fastify/error/-/error-3.3.0.tgz", - ) + DownloadTarballToStore { + tarball_cache: &Default::default(), + http_client: &Default::default(), + store_dir: store_path, + package_integrity: "sha512-aaaan1Ar8sVXj2yAXiMNCJDmS9MQ9XMlIecX2dIzzhjSHCyKo4DdXjXMs7wKW2kj6yvVRSpuQjOZ3YLrh56w==", + package_unpacked_size: Some(16697), + package_url: "https://registry.npmjs.org/@fastify/error/-/error-3.3.0.tgz", + } + .run() .await .expect_err("checksum mismatch"); diff --git a/tasks/micro-benchmark/src/main.rs b/tasks/micro-benchmark/src/main.rs index 5ad072f2e..96f1ae9a6 100644 --- a/tasks/micro-benchmark/src/main.rs +++ b/tasks/micro-benchmark/src/main.rs @@ -3,7 +3,7 @@ use std::{fs, path::Path}; use clap::Parser; use criterion::{Criterion, Throughput}; use mockito::ServerGuard; -use pacquet_tarball::download_tarball_to_store; +use pacquet_tarball::DownloadTarballToStore; use pipe_trait::Pipe; use project_root::get_project_root; use reqwest::Client; @@ -32,14 +32,14 @@ fn bench_tarball(c: &mut Criterion, server: &mut ServerGuard, fixtures_folder: & let http_client = Client::new(); let cas_map = - download_tarball_to_store( - &Default::default(), - &http_client, - dir.path(), - "sha512-dj7vjIn1Ar8sVXj2yAXiMNCJDmS9MQ9XMlIecX2dIzzhjSHCyKo4DdXjXMs7wKW2kj6yvVRSpuQjOZ3YLrh56w==", - Some(16697), - url, - ).await.unwrap(); + DownloadTarballToStore{ + tarball_cache: &Default::default(), + http_client: &http_client, + store_dir: dir.path(), + package_integrity: "sha512-dj7vjIn1Ar8sVXj2yAXiMNCJDmS9MQ9XMlIecX2dIzzhjSHCyKo4DdXjXMs7wKW2kj6yvVRSpuQjOZ3YLrh56w==", + package_unpacked_size: Some(16697), + package_url: url, + }.run().await.unwrap(); cas_map.len() }); }); From 02ee0b204692a38bae9b6fd8cfada7aef910ef20 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 20:30:11 +0700 Subject: [PATCH 175/210] docs: DownloadTarballToStore --- crates/tarball/src/lib.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/crates/tarball/src/lib.rs b/crates/tarball/src/lib.rs index 7af169c68..0fd6f4899 100644 --- a/crates/tarball/src/lib.rs +++ b/crates/tarball/src/lib.rs @@ -110,17 +110,27 @@ fn verify_checksum(data: &[u8], integrity: Integrity) -> Result { + /// Shared cache that store downloaded tarballs. pub tarball_cache: &'a Cache, + /// HTTP client to make HTTP requests. pub http_client: &'a Client, + /// Path to the store directory. pub store_dir: &'static Path, + /// Integrity of the tarball. It can be obtained from the registry index. pub package_integrity: &'a str, + /// Unpack size of the tarball. It can be obtained from the registry index. pub package_unpacked_size: Option, + /// URL to the tarball. pub package_url: &'a str, } impl<'a> DownloadTarballToStore<'a> { + /// Execute the subroutine. pub async fn run(self) -> Result>, TarballError> { let &DownloadTarballToStore { tarball_cache, package_url, .. } = &self; From d48d90873e91e11ba437da5f228eb4f32aca61e1 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 20:42:17 +0700 Subject: [PATCH 176/210] refactor: name error by step it happens --- crates/tarball/src/lib.rs | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/crates/tarball/src/lib.rs b/crates/tarball/src/lib.rs index 0fd6f4899..e94b27abe 100644 --- a/crates/tarball/src/lib.rs +++ b/crates/tarball/src/lib.rs @@ -45,12 +45,12 @@ pub struct VerifyChecksumError { #[non_exhaustive] pub enum TarballError { #[error(transparent)] - #[diagnostic(code(pacquet_tarball::request_error))] - Network(#[from] NetworkError), + #[diagnostic(code(pacquet_tarball::fetch_tarball))] + FetchTarball(#[from] NetworkError), #[error(transparent)] #[diagnostic(code(pacquet_tarball::io_error))] - Io(#[from] std::io::Error), + ReadTarballEntries(std::io::Error), #[error(transparent)] #[diagnostic(code(pacquet_tarball::parse_integrity_error))] @@ -62,19 +62,19 @@ pub enum TarballError { #[error("integrity creation failed: {}", _0)] #[diagnostic(code(pacquet_tarball::integrity_error))] - Integrity(#[from] ssri::Error), + Integrity(ssri::Error), #[error(transparent)] - #[diagnostic(code(pacquet_tarball::decompression_error))] - Decompression(#[from] InflateDecodeErrors), + #[diagnostic(code(pacquet_tarball::decode_gzip))] + DecodeGzip(InflateDecodeErrors), #[error(transparent)] #[diagnostic(transparent)] - Cafs(#[from] pacquet_cafs::CafsError), + WriteCafs(pacquet_cafs::CafsError), #[error(transparent)] #[diagnostic(code(pacquet_tarball::task_join_error))] - TaskJoin(#[from] tokio::task::JoinError), + TaskJoin(tokio::task::JoinError), } /// Value of the cache. @@ -99,10 +99,9 @@ fn decompress_gzip(gz_data: &[u8], unpacked_size: Option) -> Result DownloadTarballToStore<'a> { tracing::info!(target: "pacquet::download", ?package_url, "New cache"); - let network_error = |error| NetworkError { url: package_url.to_string(), error }; + let network_error = |error| { + TarballError::FetchTarball(NetworkError { url: package_url.to_string(), error }) + }; let response = http_client .get(package_url) .send() @@ -209,7 +210,7 @@ impl<'a> DownloadTarballToStore<'a> { decompress_gzip(&response, package_unpacked_size).map_err(TaskError::Other)?; Archive::new(Cursor::new(data)) .entries() - .map_err(TarballError::Io) + .map_err(TarballError::ReadTarballEntries) .map_err(TaskError::Other)? .filter(|entry| !entry.as_ref().unwrap().header().entry_type().is_dir()) .map(|entry| -> Result<(OsString, PathBuf), TarballError> { @@ -222,7 +223,8 @@ impl<'a> DownloadTarballToStore<'a> { let entry_path = entry.path().unwrap(); let cleaned_entry_path = entry_path.components().skip(1).collect::().into_os_string(); - let integrity = pacquet_cafs::write_sync(store_dir, &buffer)?; + let integrity = pacquet_cafs::write_sync(store_dir, &buffer) + .map_err(TarballError::WriteCafs)?; Ok((cleaned_entry_path, store_dir.join(integrity))) }) From 1cb382286e12869ea2855b07c5d103ab409384bb Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 20:52:43 +0700 Subject: [PATCH 177/210] refactor: use derive_more --- Cargo.lock | 2 +- crates/tarball/Cargo.toml | 2 +- crates/tarball/src/lib.rs | 42 +++++++++++++++++++-------------------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3d66b0495..922255ef0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1470,6 +1470,7 @@ name = "pacquet_tarball" version = "0.0.1" dependencies = [ "dashmap", + "derive_more", "miette", "pacquet_cafs", "pacquet_diagnostics", @@ -1479,7 +1480,6 @@ dependencies = [ "ssri", "tar", "tempfile", - "thiserror", "tokio", "tracing", "zune-inflate", diff --git a/crates/tarball/Cargo.toml b/crates/tarball/Cargo.toml index 5232d3c1d..4404494bf 100644 --- a/crates/tarball/Cargo.toml +++ b/crates/tarball/Cargo.toml @@ -15,6 +15,7 @@ pacquet_cafs = { workspace = true } pacquet_diagnostics = { workspace = true } dashmap = { workspace = true } +derive_more = { workspace = true } miette = { workspace = true } pipe-trait = { workspace = true } reqwest = { workspace = true } @@ -22,7 +23,6 @@ ssri = { workspace = true } tar = { workspace = true } tokio = { workspace = true } zune-inflate = { workspace = true } -thiserror = { workspace = true } tracing = { workspace = true } [dev-dependencies] diff --git a/crates/tarball/src/lib.rs b/crates/tarball/src/lib.rs index e94b27abe..fea5f7456 100644 --- a/crates/tarball/src/lib.rs +++ b/crates/tarball/src/lib.rs @@ -7,72 +7,72 @@ use std::{ }; use dashmap::DashMap; +use derive_more::{Display, Error, From}; use miette::Diagnostic; use pipe_trait::Pipe; use reqwest::Client; use ssri::{Integrity, IntegrityChecker}; use tar::Archive; -use thiserror::Error; use tokio::sync::{Notify, RwLock}; use tracing::instrument; use zune_inflate::{errors::InflateDecodeErrors, DeflateDecoder, DeflateOptions}; -#[derive(Error, Debug, Diagnostic)] -#[error("Failed to fetch {url}: {error}")] +#[derive(Debug, Display, Error, Diagnostic)] +#[display(fmt = "Failed to fetch {url}: {error}")] pub struct NetworkError { pub url: String, pub error: reqwest::Error, } -#[derive(Error, Debug, Diagnostic)] -#[error("Cannot parse {integrity:?} from {url} as an integrity: {error}")] +#[derive(Debug, Display, Error, Diagnostic)] +#[display(fmt = "Cannot parse {integrity:?} from {url} as an integrity: {error}")] pub struct ParseIntegrityError { pub url: String, pub integrity: String, - #[source] + #[error(source)] pub error: ssri::Error, } -#[derive(Error, Debug, Diagnostic)] -#[error("Failed to verify the integrity of {url}: {error}")] +#[derive(Debug, Display, Error, Diagnostic)] +#[display(fmt = "Failed to verify the integrity of {url}: {error}")] pub struct VerifyChecksumError { pub url: String, - #[source] + #[error(source)] pub error: ssri::Error, } -#[derive(Error, Debug, Diagnostic)] +#[derive(Debug, Display, Error, From, Diagnostic)] #[non_exhaustive] pub enum TarballError { - #[error(transparent)] #[diagnostic(code(pacquet_tarball::fetch_tarball))] - FetchTarball(#[from] NetworkError), + FetchTarball(NetworkError), - #[error(transparent)] + #[from(ignore)] #[diagnostic(code(pacquet_tarball::io_error))] ReadTarballEntries(std::io::Error), - #[error(transparent)] #[diagnostic(code(pacquet_tarball::parse_integrity_error))] - ParseIntegrity(#[from] ParseIntegrityError), + ParseIntegrity(ParseIntegrityError), - #[error(transparent)] #[diagnostic(code(pacquet_tarball::verify_checksum_error))] - Checksum(#[from] VerifyChecksumError), + Checksum(VerifyChecksumError), - #[error("integrity creation failed: {}", _0)] + #[from(ignore)] + #[display(fmt = "Integrity creation failed: {_0}")] #[diagnostic(code(pacquet_tarball::integrity_error))] Integrity(ssri::Error), - #[error(transparent)] + #[from(ignore)] + #[display(fmt = "Failed to decode gzip: {_0}")] #[diagnostic(code(pacquet_tarball::decode_gzip))] DecodeGzip(InflateDecodeErrors), - #[error(transparent)] + #[from(ignore)] + #[display(fmt = "Failed to write cafs: {_0}")] #[diagnostic(transparent)] WriteCafs(pacquet_cafs::CafsError), - #[error(transparent)] + #[from(ignore)] #[diagnostic(code(pacquet_tarball::task_join_error))] TaskJoin(tokio::task::JoinError), } From 246b4881be54c31eec848844c969645b7a3707b0 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 20:58:16 +0700 Subject: [PATCH 178/210] fix(test): macOS on CI --- crates/cli/tests/store.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/cli/tests/store.rs b/crates/cli/tests/store.rs index 4b23616e9..62502d3b0 100644 --- a/crates/cli/tests/store.rs +++ b/crates/cli/tests/store.rs @@ -1,5 +1,6 @@ use command_extra::CommandExtra; use pacquet_testing_utils::bin::pacquet_with_temp_cwd; +use pipe_trait::Pipe; use pretty_assertions::assert_eq; use std::fs; @@ -20,6 +21,6 @@ fn store_path_should_return_store_dir_from_npmrc() { eprintln!("Stdout"); assert_eq!( String::from_utf8_lossy(&output.stdout).trim_end(), - dir.path().join("foo/bar").to_string_lossy(), + dir.path().pipe(fs::canonicalize).unwrap().join("foo/bar").to_string_lossy(), ); } From c25d9c8fe66443748c6cdf5d90cd84e138fa1c98 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 21:17:52 +0700 Subject: [PATCH 179/210] chore(cargo): use derive_more@1.0.0-beta.3 --- Cargo.lock | 86 +++++++++---------- Cargo.toml | 2 +- crates/executor/src/lib.rs | 4 +- crates/lockfile/src/comver.rs | 8 +- crates/lockfile/src/dependency_path.rs | 6 +- crates/lockfile/src/load_lockfile.rs | 6 +- crates/lockfile/src/lockfile_version.rs | 2 +- crates/lockfile/src/pkg_name.rs | 4 +- crates/lockfile/src/pkg_name_suffix.rs | 18 ++-- crates/lockfile/src/pkg_ver_peer.rs | 6 +- crates/package_manager/src/add.rs | 4 +- .../src/create_virtual_dir_by_snapshot.rs | 2 +- crates/package_manager/src/link_file.rs | 4 +- crates/package_manager/src/symlink_package.rs | 4 +- crates/registry/src/package_tag.rs | 2 +- crates/tarball/src/lib.rs | 12 +-- 16 files changed, 84 insertions(+), 86 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 922255ef0..3c18e8d30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -113,7 +113,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn", ] [[package]] @@ -278,7 +278,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.28", + "syn", ] [[package]] @@ -324,9 +324,12 @@ dependencies = [ [[package]] name = "convert_case" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] [[package]] name = "core-foundation" @@ -449,15 +452,24 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.17" +version = "1.0.0-beta.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "f1335e0609db169713d97c340dd769773c6c63cd953c8fcf1063043fd3d6dd11" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0-beta.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df541e0e2a8069352be228ce4b85a1da6f59bfd325e56f57e4b241babbc3f832" dependencies = [ "convert_case", "proc-macro2", "quote", - "rustc_version", - "syn 1.0.109", + "syn", + "unicode-xid", ] [[package]] @@ -640,7 +652,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn", ] [[package]] @@ -1059,7 +1071,7 @@ checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn", ] [[package]] @@ -1227,7 +1239,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn", ] [[package]] @@ -1817,15 +1829,6 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] - [[package]] name = "rustix" version = "0.38.13" @@ -1898,12 +1901,6 @@ dependencies = [ "libc", ] -[[package]] -name = "semver" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" - [[package]] name = "serde" version = "1.0.188" @@ -1921,7 +1918,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn", ] [[package]] @@ -2103,7 +2100,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.28", + "syn", ] [[package]] @@ -2134,17 +2131,6 @@ dependencies = [ "is-terminal", ] -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.28" @@ -2230,7 +2216,7 @@ checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn", ] [[package]] @@ -2296,7 +2282,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn", ] [[package]] @@ -2349,7 +2335,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn", ] [[package]] @@ -2430,12 +2416,24 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + [[package]] name = "unicode-width" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + [[package]] name = "unsafe-libyaml" version = "0.2.9" @@ -2538,7 +2536,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.28", + "syn", "wasm-bindgen-shared", ] @@ -2572,7 +2570,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/Cargo.toml b/Cargo.toml index 32dcea25a..2b7ace002 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ async-recursion = { version = "1.0.5" } clap = { version = "4", features = ["derive", "string"] } command-extra = { version = "1.0.0" } dashmap = { version = "5.5.3" } -derive_more = { version = "0.99.17" } +derive_more = { version = "1.0.0-beta.3", features = ["full"] } home = { version = "0.5.5" } insta = { version = "1.32.0", features = ["yaml", "glob", "walkdir"] } itertools = { version = "0.11.0" } diff --git a/crates/executor/src/lib.rs b/crates/executor/src/lib.rs index 95feb1bd8..8eb379ddf 100644 --- a/crates/executor/src/lib.rs +++ b/crates/executor/src/lib.rs @@ -5,11 +5,11 @@ use std::process::Command; #[derive(Debug, Display, Error, Diagnostic)] #[non_exhaustive] pub enum ExecutorError { - #[display(fmt = "Failed to spawn command: {_0}")] + #[display("Failed to spawn command: {_0}")] #[diagnostic(code(pacquet_executor::spawn_command))] SpawnCommand(#[error(source)] std::io::Error), - #[display(fmt = "Process exits with an error: {_0}")] + #[display("Process exits with an error: {_0}")] #[diagnostic(code(pacquet_executor::wait_process))] WaitProcess(#[error(source)] std::io::Error), } diff --git a/crates/lockfile/src/comver.rs b/crates/lockfile/src/comver.rs index 291b314b9..b6b740006 100644 --- a/crates/lockfile/src/comver.rs +++ b/crates/lockfile/src/comver.rs @@ -6,7 +6,7 @@ use std::{num::ParseIntError, str::FromStr}; /// /// It contains only major and minor. #[derive(Debug, Display, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -#[display(fmt = "{major}.{minor}")] +#[display("{major}.{minor}")] #[serde(try_from = "&'de str", into = "String")] pub struct ComVer { pub major: u16, @@ -23,11 +23,11 @@ impl ComVer { /// Error when parsing [`ComVer`] from a string. #[derive(Debug, Display, Error)] pub enum ParseComVerError { - #[display(fmt = "Dot is missing")] + #[display("Dot is missing")] MissingDot, - #[display(fmt = "Major is not a valid number: {_0}")] + #[display("Major is not a valid number: {_0}")] InvalidMajor(ParseIntError), - #[display(fmt = "Minor is not a valid number: {_0}")] + #[display("Minor is not a valid number: {_0}")] InvalidMinor(ParseIntError), } diff --git a/crates/lockfile/src/dependency_path.rs b/crates/lockfile/src/dependency_path.rs index 2e0f27eea..bc0e2f86f 100644 --- a/crates/lockfile/src/dependency_path.rs +++ b/crates/lockfile/src/dependency_path.rs @@ -17,7 +17,7 @@ use std::str::FromStr; /// * `registry.npmjs.com/ts-node@10.9.1(@types/node@18.7.19)(typescript@5.1.6)` /// * `registry.node-modules.io/ts-node@10.9.1(@types/node@18.7.19)(typescript@5.1.6)` #[derive(Debug, Display, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)] -#[display(fmt = "{}/{package_specifier}", "custom_registry.as_deref().unwrap_or_default()")] +#[display("{}/{package_specifier}", custom_registry.as_deref().unwrap_or_default())] #[serde(try_from = "&'de str", into = "String")] pub struct DependencyPath { pub custom_registry: Option, @@ -27,9 +27,9 @@ pub struct DependencyPath { /// Error when parsing [`DependencyPath`] from a string. #[derive(Debug, Display, Error)] pub enum ParseDependencyPathError { - #[display(fmt = "Invalid syntax")] + #[display("Invalid syntax")] InvalidSyntax, - #[display(fmt = "Failed to parse specifier: {_0}")] + #[display("Failed to parse specifier: {_0}")] ParsePackageSpecifierFailure(ParsePkgNameVerPeerError), } diff --git a/crates/lockfile/src/load_lockfile.rs b/crates/lockfile/src/load_lockfile.rs index 83b7f9b87..2f4a6bec0 100644 --- a/crates/lockfile/src/load_lockfile.rs +++ b/crates/lockfile/src/load_lockfile.rs @@ -11,15 +11,15 @@ use std::{ #[derive(Debug, Display, Error, Diagnostic)] #[non_exhaustive] pub enum LoadLockfileError { - #[display(fmt = "Failed to get current_dir: {_0}")] + #[display("Failed to get current_dir: {_0}")] #[diagnostic(code(pacquet_lockfile::current_dir))] CurrentDir(io::Error), - #[display(fmt = "Failed to read lockfile content: {_0}")] + #[display("Failed to read lockfile content: {_0}")] #[diagnostic(code(pacquet_lockfile::read_file))] ReadFile(io::Error), - #[display(fmt = "Failed to parse lockfile content as YAML: {_0}")] + #[display("Failed to parse lockfile content as YAML: {_0}")] #[diagnostic(code(pacquet_lockfile::parse_yaml))] ParseYaml(serde_yaml::Error), } diff --git a/crates/lockfile/src/lockfile_version.rs b/crates/lockfile/src/lockfile_version.rs index 4fb6ccc6b..bf0c3fbde 100644 --- a/crates/lockfile/src/lockfile_version.rs +++ b/crates/lockfile/src/lockfile_version.rs @@ -19,7 +19,7 @@ impl LockfileVersion { /// Error when [`ComVer`] fails compatibility check. #[derive(Debug, Display, Error)] pub enum LockfileVersionError { - #[display(fmt = "The lockfileVersion of {_0} is incompatible with {MAJOR}.x")] + #[display("The lockfileVersion of {_0} is incompatible with {MAJOR}.x")] IncompatibleMajor(#[error(not(source))] ComVer), } diff --git a/crates/lockfile/src/pkg_name.rs b/crates/lockfile/src/pkg_name.rs index d8c695427..f58d6799f 100644 --- a/crates/lockfile/src/pkg_name.rs +++ b/crates/lockfile/src/pkg_name.rs @@ -21,9 +21,9 @@ pub struct PkgName { /// Error when parsing [`PkgName`] from a string input. #[derive(Debug, Display, Error)] pub enum ParsePkgNameError { - #[display(fmt = "Missing bare name")] + #[display("Missing bare name")] MissingName, - #[display(fmt = "Name is empty")] + #[display("Name is empty")] EmptyName, } diff --git a/crates/lockfile/src/pkg_name_suffix.rs b/crates/lockfile/src/pkg_name_suffix.rs index 6f1e5e6a6..d5e905fa3 100644 --- a/crates/lockfile/src/pkg_name_suffix.rs +++ b/crates/lockfile/src/pkg_name_suffix.rs @@ -2,7 +2,7 @@ use crate::{ParsePkgNameError, PkgName}; use derive_more::{Display, Error}; use serde::{Deserialize, Serialize}; use split_first_char::SplitFirstChar; -use std::{fmt::Display, str::FromStr}; +use std::str::FromStr; /// Syntax: `{name}@{suffix}` /// @@ -10,8 +10,8 @@ use std::{fmt::Display, str::FromStr}; /// * `ts-node@10.9.1`, `@types/node@18.7.19`, `typescript@5.1.6` /// * `react-json-view@1.21.3(@types/react@17.0.49)(react-dom@17.0.2)(react@17.0.2)` #[derive(Debug, Display, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)] -#[display(fmt = "{name}@{suffix}")] -#[display(bound = "Suffix: Display")] +#[display("{name}@{suffix}")] +#[display(bound(Suffix: Display))] #[serde(try_from = "&'de str", into = "String")] #[serde(bound( deserialize = "Suffix: FromStr, Suffix::Err: Display", @@ -31,17 +31,17 @@ impl PkgNameSuffix { /// Error when parsing [`PkgNameSuffix`] from a string. #[derive(Debug, Display, Error)] -#[display(bound = "ParseSuffixError: Display")] +#[display(bound(ParseSuffixError: Display))] pub enum ParsePkgNameSuffixError { - #[display(fmt = "Input is empty")] + #[display("Input is empty")] EmptyInput, - #[display(fmt = "Suffix is missing")] + #[display("Suffix is missing")] MissingSuffix, - #[display(fmt = "Name is empty")] + #[display("Name is empty")] EmptyName, - #[display(fmt = "Failed to parse suffix: {_0}")] + #[display("Failed to parse suffix: {_0}")] ParseSuffixFailure(#[error(source)] ParseSuffixError), - #[display(fmt = "Failed to parse name: {_0}")] + #[display("Failed to parse name: {_0}")] ParseNameFailure(#[error(source)] ParsePkgNameError), } diff --git a/crates/lockfile/src/pkg_ver_peer.rs b/crates/lockfile/src/pkg_ver_peer.rs index a5c3acd32..299725868 100644 --- a/crates/lockfile/src/pkg_ver_peer.rs +++ b/crates/lockfile/src/pkg_ver_peer.rs @@ -10,7 +10,7 @@ use std::str::FromStr; /// /// **NOTE:** The peer part isn't guaranteed to be correct. It is only assumed to be. #[derive(Debug, Display, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -#[display(fmt = "{version}{peer}")] +#[display("{version}{peer}")] #[serde(try_from = "&'de str", into = "String")] pub struct PkgVerPeer { version: Version, @@ -38,9 +38,9 @@ impl PkgVerPeer { /// Error when parsing [`PkgVerPeer`] from a string. #[derive(Debug, Display, Error)] pub enum ParsePkgVerPeerError { - #[display(fmt = "Failed to parse the version part: {_0}")] + #[display("Failed to parse the version part: {_0}")] ParseVersionFailure(#[error(source)] SemverError), - #[display(fmt = "Mismatch parenthesis")] + #[display("Mismatch parenthesis")] MismatchParenthesis, } diff --git a/crates/package_manager/src/add.rs b/crates/package_manager/src/add.rs index 38ab3ccaa..2936ee627 100644 --- a/crates/package_manager/src/add.rs +++ b/crates/package_manager/src/add.rs @@ -37,9 +37,9 @@ where /// Error type of [`Add`]. #[derive(Debug, Display, Error, Diagnostic)] pub enum AddError { - #[display(fmt = "Failed to add package to manifest: {_0}")] + #[display("Failed to add package to manifest: {_0}")] AddDependencyToPackageJson(#[error(source)] PackageJsonError), - #[display(fmt = "Failed save the manifest file: {_0}")] + #[display("Failed save the manifest file: {_0}")] SavePackageJson(#[error(source)] PackageJsonError), } diff --git a/crates/package_manager/src/create_virtual_dir_by_snapshot.rs b/crates/package_manager/src/create_virtual_dir_by_snapshot.rs index f357ac4d1..3ba6eb8e8 100644 --- a/crates/package_manager/src/create_virtual_dir_by_snapshot.rs +++ b/crates/package_manager/src/create_virtual_dir_by_snapshot.rs @@ -28,7 +28,7 @@ pub struct CreateVirtualDirBySnapshot<'a> { /// Error type of [`CreateVirtualDirBySnapshot`]. #[derive(Debug, Display, Error, Diagnostic)] pub enum CreateVirtualDirError { - #[display(fmt = "Failed to recursively create node_modules directory at {dir:?}: {error}")] + #[display("Failed to recursively create node_modules directory at {dir:?}: {error}")] #[diagnostic(code(pacquet_package_manager::create_node_modules_dir))] CreateNodeModulesDir { dir: PathBuf, diff --git a/crates/package_manager/src/link_file.rs b/crates/package_manager/src/link_file.rs index 229cfb569..6805515c2 100644 --- a/crates/package_manager/src/link_file.rs +++ b/crates/package_manager/src/link_file.rs @@ -8,13 +8,13 @@ use std::{ /// Error type for [`link_file`]. #[derive(Debug, Display, Error, Diagnostic)] pub enum LinkFileError { - #[display(fmt = "cannot create directory at {dirname:?}: {error}")] + #[display("cannot create directory at {dirname:?}: {error}")] CreateDir { dirname: PathBuf, #[error(source)] error: io::Error, }, - #[display(fmt = "fail to create a link from {from:?} to {to:?}: {error}")] + #[display("fail to create a link from {from:?} to {to:?}: {error}")] CreateLink { from: PathBuf, to: PathBuf, diff --git a/crates/package_manager/src/symlink_package.rs b/crates/package_manager/src/symlink_package.rs index 979ecc291..76834e082 100644 --- a/crates/package_manager/src/symlink_package.rs +++ b/crates/package_manager/src/symlink_package.rs @@ -10,14 +10,14 @@ use std::{ /// Error type for [`symlink_package`]. #[derive(Debug, Display, Error, Diagnostic)] pub enum SymlinkPackageError { - #[display(fmt = "Failed to create directory at {dir:?}: {error}")] + #[display("Failed to create directory at {dir:?}: {error}")] CreateParentDir { dir: PathBuf, #[error(source)] error: io::Error, }, - #[display(fmt = "Failed to create symlink at {symlink_path:?} to {symlink_target:?}: {error}")] + #[display("Failed to create symlink at {symlink_path:?} to {symlink_target:?}: {error}")] SymlinkDir { symlink_target: PathBuf, symlink_path: PathBuf, diff --git a/crates/registry/src/package_tag.rs b/crates/registry/src/package_tag.rs index 30a4e8276..680a72f01 100644 --- a/crates/registry/src/package_tag.rs +++ b/crates/registry/src/package_tag.rs @@ -6,7 +6,7 @@ use std::str::FromStr; #[derive(Debug, Display, From, TryInto)] pub enum PackageTag { /// Literally `latest``. - #[display(fmt = "latest")] + #[display("latest")] Latest, /// Pinned version. Version(Version), diff --git a/crates/tarball/src/lib.rs b/crates/tarball/src/lib.rs index fea5f7456..4f37b9861 100644 --- a/crates/tarball/src/lib.rs +++ b/crates/tarball/src/lib.rs @@ -18,14 +18,14 @@ use tracing::instrument; use zune_inflate::{errors::InflateDecodeErrors, DeflateDecoder, DeflateOptions}; #[derive(Debug, Display, Error, Diagnostic)] -#[display(fmt = "Failed to fetch {url}: {error}")] +#[display("Failed to fetch {url}: {error}")] pub struct NetworkError { pub url: String, pub error: reqwest::Error, } #[derive(Debug, Display, Error, Diagnostic)] -#[display(fmt = "Cannot parse {integrity:?} from {url} as an integrity: {error}")] +#[display("Cannot parse {integrity:?} from {url} as an integrity: {error}")] pub struct ParseIntegrityError { pub url: String, pub integrity: String, @@ -34,7 +34,7 @@ pub struct ParseIntegrityError { } #[derive(Debug, Display, Error, Diagnostic)] -#[display(fmt = "Failed to verify the integrity of {url}: {error}")] +#[display("Failed to verify the integrity of {url}: {error}")] pub struct VerifyChecksumError { pub url: String, #[error(source)] @@ -58,17 +58,17 @@ pub enum TarballError { Checksum(VerifyChecksumError), #[from(ignore)] - #[display(fmt = "Integrity creation failed: {_0}")] + #[display("Integrity creation failed: {_0}")] #[diagnostic(code(pacquet_tarball::integrity_error))] Integrity(ssri::Error), #[from(ignore)] - #[display(fmt = "Failed to decode gzip: {_0}")] + #[display("Failed to decode gzip: {_0}")] #[diagnostic(code(pacquet_tarball::decode_gzip))] DecodeGzip(InflateDecodeErrors), #[from(ignore)] - #[display(fmt = "Failed to write cafs: {_0}")] + #[display("Failed to write cafs: {_0}")] #[diagnostic(transparent)] WriteCafs(pacquet_cafs::CafsError), From 8d80da330bf420d24cdde085711c753c758b967d Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 21:39:14 +0700 Subject: [PATCH 180/210] fix(test): windows --- Cargo.lock | 7 +++++++ Cargo.toml | 1 + crates/cli/Cargo.toml | 1 + crates/cli/tests/store.rs | 2 +- 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 3c18e8d30..590e7f7be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -500,6 +500,12 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +[[package]] +name = "dunce" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" + [[package]] name = "either" version = "1.9.0" @@ -1310,6 +1316,7 @@ dependencies = [ "clap", "command-extra", "derive_more", + "dunce", "home", "insta", "miette", diff --git a/Cargo.toml b/Cargo.toml index 2b7ace002..06a62c762 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ clap = { version = "4", features = ["derive", "string"] } command-extra = { version = "1.0.0" } dashmap = { version = "5.5.3" } derive_more = { version = "1.0.0-beta.3", features = ["full"] } +dunce = { version = "1.0.4" } home = { version = "0.5.5" } insta = { version = "1.32.0", features = ["yaml", "glob", "walkdir"] } itertools = { version = "0.11.0" } diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 3de91f268..109647b48 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -39,6 +39,7 @@ tracing = { workspace = true } pacquet_testing_utils = { workspace = true } assert_cmd = { workspace = true } +dunce = { workspace = true } command-extra = { workspace = true } insta = { workspace = true } pretty_assertions = { workspace = true } diff --git a/crates/cli/tests/store.rs b/crates/cli/tests/store.rs index 62502d3b0..8a2e9a0c8 100644 --- a/crates/cli/tests/store.rs +++ b/crates/cli/tests/store.rs @@ -21,6 +21,6 @@ fn store_path_should_return_store_dir_from_npmrc() { eprintln!("Stdout"); assert_eq!( String::from_utf8_lossy(&output.stdout).trim_end(), - dir.path().pipe(fs::canonicalize).unwrap().join("foo/bar").to_string_lossy(), + dir.path().pipe(dunce::canonicalize).unwrap().join("foo/bar").to_string_lossy(), ); } From 05870a3fd523468b67a4f1f99254b14723a3911b Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 21:46:42 +0700 Subject: [PATCH 181/210] chore: remove accidental file --- crates/cli/package.json | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 crates/cli/package.json diff --git a/crates/cli/package.json b/crates/cli/package.json deleted file mode 100644 index 42164e7af..000000000 --- a/crates/cli/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "", - "license": "ISC", - "dependencies": { - "is-even": "^1.0.0" - } -} \ No newline at end of file From 5088dac675dd20fa545ec3d7c75af8b04e39f69d Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 21:49:18 +0700 Subject: [PATCH 182/210] chore(cargo): remove unused dependency --- Cargo.lock | 1 - crates/cli/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 590e7f7be..6252fc70f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1337,7 +1337,6 @@ dependencies = [ "serde_json", "tempfile", "tokio", - "tracing", ] [[package]] diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 109647b48..8452ee795 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -33,7 +33,6 @@ miette = { workspace = true } reqwest = { workspace = true } pipe-trait = { workspace = true } tokio = { workspace = true } -tracing = { workspace = true } [dev-dependencies] pacquet_testing_utils = { workspace = true } From 1a0d2c86b90b331dbe9cbd481e5d9689038b3f43 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 21:54:16 +0700 Subject: [PATCH 183/210] fix(test): windows, again --- crates/cli/tests/store.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/cli/tests/store.rs b/crates/cli/tests/store.rs index 8a2e9a0c8..c9cce826d 100644 --- a/crates/cli/tests/store.rs +++ b/crates/cli/tests/store.rs @@ -19,8 +19,14 @@ fn store_path_should_return_store_dir_from_npmrc() { assert!(output.status.success()); eprintln!("Stdout"); + let normalize = |path: &str| path.replace('\\', "/"); assert_eq!( - String::from_utf8_lossy(&output.stdout).trim_end(), - dir.path().pipe(dunce::canonicalize).unwrap().join("foo/bar").to_string_lossy(), + String::from_utf8_lossy(&output.stdout).trim_end().pipe(normalize), + dir.path() + .pipe(dunce::canonicalize) + .unwrap() + .join("foo/bar") + .to_string_lossy() + .pipe_as_ref(normalize), ); } From 9b170913d5941e39f21f2b8b3304f060d4fa3bee Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 21:58:22 +0700 Subject: [PATCH 184/210] chore(cargo): remove unused dependency --- Cargo.lock | 1 - crates/diagnostics/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6252fc70f..8c131710d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1344,7 +1344,6 @@ name = "pacquet_diagnostics" version = "0.0.1" dependencies = [ "miette", - "thiserror", "tracing", "tracing-subscriber", ] diff --git a/crates/diagnostics/Cargo.toml b/crates/diagnostics/Cargo.toml index 0053f7b13..a9e667a98 100644 --- a/crates/diagnostics/Cargo.toml +++ b/crates/diagnostics/Cargo.toml @@ -12,6 +12,5 @@ repository.workspace = true [dependencies] miette = { workspace = true } -thiserror = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true } From ca110d9122b020b3eee89ab1386ccb199f9409f7 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 22:09:55 +0700 Subject: [PATCH 185/210] refactor: replace `thiserror` with `derive_more` * `thiserror` cannot handle generic trait bound. * `derive_more` is already used to generate custom string type in the lockfile. * one less macro crate leads to slightly faster compile time. --- Cargo.lock | 5 ++--- Cargo.toml | 1 - crates/cafs/Cargo.toml | 6 +++--- crates/cafs/src/lib.rs | 7 +++---- crates/package_json/Cargo.toml | 10 +++++----- crates/package_json/src/lib.rs | 27 ++++++++++++++------------- crates/registry/Cargo.toml | 1 - crates/registry/src/lib.rs | 29 +++++++++++++++-------------- 8 files changed, 42 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8c131710d..ecd268485 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1301,11 +1301,11 @@ checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" name = "pacquet_cafs" version = "0.0.1" dependencies = [ + "derive_more", "miette", "pretty_assertions", "ssri", "tempfile", - "thiserror", ] [[package]] @@ -1425,6 +1425,7 @@ dependencies = [ name = "pacquet_package_json" version = "0.0.1" dependencies = [ + "derive_more", "insta", "miette", "pipe-trait", @@ -1433,7 +1434,6 @@ dependencies = [ "serde_json", "strum", "tempfile", - "thiserror", ] [[package]] @@ -1478,7 +1478,6 @@ dependencies = [ "serde", "serde_json", "tempfile", - "thiserror", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index 06a62c762..8f0e2152e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,7 +54,6 @@ ssri = { version = "9.0.0" } strum = { version = "0.25.0", features = ["derive"] } tar = { version = "0.4.40" } text-block-macros = { version = "0.1.1" } -thiserror = { version = "1.0.48" } tracing = { version = "0.1.37" } tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] } diff --git a/crates/cafs/Cargo.toml b/crates/cafs/Cargo.toml index 66889dc70..bc13baa2f 100644 --- a/crates/cafs/Cargo.toml +++ b/crates/cafs/Cargo.toml @@ -11,9 +11,9 @@ license.workspace = true repository.workspace = true [dependencies] -miette = { workspace = true } -ssri = { workspace = true } -thiserror = { workspace = true } +derive_more = { workspace = true } +miette = { workspace = true } +ssri = { workspace = true } [dev-dependencies] tempfile = { workspace = true } diff --git a/crates/cafs/src/lib.rs b/crates/cafs/src/lib.rs index 6e620c293..c55179e26 100644 --- a/crates/cafs/src/lib.rs +++ b/crates/cafs/src/lib.rs @@ -5,16 +5,15 @@ use std::{ path::{Path, PathBuf}, }; +use derive_more::{Display, Error, From}; use miette::Diagnostic; use ssri::{Algorithm, IntegrityOpts}; -use thiserror::Error; -#[derive(Error, Debug, Diagnostic)] +#[derive(Debug, Display, Error, From, Diagnostic)] #[non_exhaustive] pub enum CafsError { - #[error(transparent)] #[diagnostic(code(pacquet_cafs::io_error))] - Io(#[from] std::io::Error), + Io(std::io::Error), // TODO: remove derive(From), split this variant } enum FileType { diff --git a/crates/package_json/Cargo.toml b/crates/package_json/Cargo.toml index fe8ca6c5d..dc058209c 100644 --- a/crates/package_json/Cargo.toml +++ b/crates/package_json/Cargo.toml @@ -11,11 +11,11 @@ license.workspace = true repository.workspace = true [dependencies] -miette = { workspace = true } -serde = { workspace = true } -serde_json = { workspace = true } -strum = { workspace = true } -thiserror = { workspace = true } +derive_more = { workspace = true } +miette = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +strum = { workspace = true } [dev-dependencies] pipe-trait = { workspace = true } diff --git a/crates/package_json/src/lib.rs b/crates/package_json/src/lib.rs index de0065a75..4cc3f1d43 100644 --- a/crates/package_json/src/lib.rs +++ b/crates/package_json/src/lib.rs @@ -4,41 +4,42 @@ use std::{ path::{Path, PathBuf}, }; +use derive_more::{Display, Error, From}; use miette::Diagnostic; use serde::{Deserialize, Serialize}; use serde_json::{json, Map, Value}; use strum::IntoStaticStr; -use thiserror::Error; -#[derive(Error, Debug, Diagnostic)] +#[derive(Debug, Display, Error, From, Diagnostic)] #[non_exhaustive] pub enum PackageJsonError { - #[error(transparent)] #[diagnostic(code(pacquet_package_json::serialization_error))] - Serialization(#[from] serde_json::Error), + Serialization(serde_json::Error), // TODO: remove derive(From), split this variant - #[error(transparent)] #[diagnostic(code(pacquet_package_json::io_error))] - Io(#[from] std::io::Error), + Io(std::io::Error), // TODO: remove derive(From), split this variant - #[error("package.json file already exists")] + #[display("package.json file already exists")] #[diagnostic( code(pacquet_package_json::already_exist_error), help("Your current working directory already has a package.json file.") )] AlreadyExist, - #[error("invalid attribute: {0}")] + #[from(ignore)] // TODO: remove this after derive(From) has been removed + #[display("invalid attribute: {_0}")] #[diagnostic(code(pacquet_package_json::invalid_attribute))] - InvalidAttribute(String), + InvalidAttribute(#[error(not(source))] String), - #[error("No package.json was found in {0}")] + #[from(ignore)] // TODO: remove this after derive(From) has been removed + #[display("No package.json was found in {_0}")] #[diagnostic(code(pacquet_package_json::no_import_manifest_found))] - NoImporterManifestFound(String), + NoImporterManifestFound(#[error(not(source))] String), - #[error("Missing script: \"{0}\"")] + #[from(ignore)] // TODO: remove this after derive(From) has been removed + #[display("Missing script: {_0:?}")] #[diagnostic(code(pacquet_package_json::no_script_error))] - NoScript(String), + NoScript(#[error(not(source))] String), } #[derive(Debug, Clone, Copy, PartialEq, IntoStaticStr)] diff --git a/crates/registry/Cargo.toml b/crates/registry/Cargo.toml index 00bbed43a..9a814d190 100644 --- a/crates/registry/Cargo.toml +++ b/crates/registry/Cargo.toml @@ -21,7 +21,6 @@ serde = { workspace = true } serde_json = { workspace = true } tokio = { workspace = true } miette = { workspace = true } -thiserror = { workspace = true } [dev-dependencies] pretty_assertions = { workspace = true } diff --git a/crates/registry/src/lib.rs b/crates/registry/src/lib.rs index 30c4aa2f9..d6e62def2 100644 --- a/crates/registry/src/lib.rs +++ b/crates/registry/src/lib.rs @@ -8,37 +8,38 @@ pub use package_distribution::PackageDistribution; pub use package_tag::PackageTag; pub use package_version::PackageVersion; +use derive_more::{Display, Error, From}; use miette::Diagnostic; -use thiserror::Error; -#[derive(Debug, Error)] -#[error("failed to request {url}: {error}")] +#[derive(Debug, Display, Error)] +#[display("Failed to request {url}: {error}")] pub struct NetworkError { pub url: String, - #[source] + #[error(source)] pub error: reqwest::Error, } -#[derive(Error, Debug, Diagnostic)] +#[derive(Debug, Display, Error, From, Diagnostic)] #[non_exhaustive] pub enum RegistryError { - #[error("missing latest tag on {0}")] + #[from(ignore)] // TODO: remove this after derive(From) has been removed + #[display("Missing latest tag on {_0}")] #[diagnostic(code(pacquet_registry::missing_latest_tag))] - MissingLatestTag(String), + MissingLatestTag(#[error(not(source))] String), - #[error("missing version {0} on package {1}")] + #[from(ignore)] // TODO: remove this after derive(From) has been removed + #[display("Missing version {_0} on package {_1}")] #[diagnostic(code(pacquet_registry::missing_version_release))] MissingVersionRelease(String, String), - #[error(transparent)] #[diagnostic(code(pacquet_registry::network_error))] - Network(#[from] NetworkError), + Network(NetworkError), // TODO: remove derive(Error), split this variant - #[error(transparent)] #[diagnostic(code(pacquet_registry::io_error))] - Io(#[from] std::io::Error), + Io(std::io::Error), // TODO: remove derive(Error), split this variant - #[error("serialization failed: {0}")] + #[from(ignore)] // TODO: remove this after derive(From) has been removed + #[display("Serialization failed: {_0}")] #[diagnostic(code(pacquet_registry::serialization_error))] - Serialization(String), + Serialization(#[error(not(source))] String), } From 40257660f735f66370d909279a4c7683e8374752 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Sun, 15 Oct 2023 22:22:06 +0700 Subject: [PATCH 186/210] fix(test): windows, macos --- crates/cli/tests/store.rs | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/crates/cli/tests/store.rs b/crates/cli/tests/store.rs index c9cce826d..fabd48022 100644 --- a/crates/cli/tests/store.rs +++ b/crates/cli/tests/store.rs @@ -2,7 +2,21 @@ use command_extra::CommandExtra; use pacquet_testing_utils::bin::pacquet_with_temp_cwd; use pipe_trait::Pipe; use pretty_assertions::assert_eq; -use std::fs; +use std::{ + fs, + path::{Path, PathBuf}, +}; + +/// Handle the slight difference between OSes. +/// +/// **TODO:** may be we should have handle them in the production code instead? +fn canonicalize(path: &Path) -> PathBuf { + if cfg!(windows) { + path.to_path_buf() + } else { + dunce::canonicalize(path).expect("canonicalize path") + } +} #[test] fn store_path_should_return_store_dir_from_npmrc() { @@ -22,11 +36,6 @@ fn store_path_should_return_store_dir_from_npmrc() { let normalize = |path: &str| path.replace('\\', "/"); assert_eq!( String::from_utf8_lossy(&output.stdout).trim_end().pipe(normalize), - dir.path() - .pipe(dunce::canonicalize) - .unwrap() - .join("foo/bar") - .to_string_lossy() - .pipe_as_ref(normalize), + dir.path().pipe(canonicalize).join("foo/bar").to_string_lossy().pipe_as_ref(normalize), ); } From 11924f4656387898698f48ab801f7dfa128f67af Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 16 Oct 2023 13:16:33 +0700 Subject: [PATCH 187/210] refactor: use getters --- crates/cli/src/cli_args/add.rs | 43 +++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/crates/cli/src/cli_args/add.rs b/crates/cli/src/cli_args/add.rs index 498e354bc..b260cc45d 100644 --- a/crates/cli/src/cli_args/add.rs +++ b/crates/cli/src/cli_args/add.rs @@ -22,19 +22,44 @@ pub struct AddDependencyOptions { } impl AddDependencyOptions { + /// Whether to add entry to `"dependencies"`. + /// + /// **NOTE:** no `--save-*` flags implies save as prod. + #[inline(always)] + fn save_prod(&self) -> bool { + let &AddDependencyOptions { save_prod, save_dev, save_optional, save_peer } = self; + save_prod || (!save_dev && !save_optional && !save_peer) + } + + /// Whether to add entry to `"devDependencies"`. + /// + /// **NOTE:** `--save-peer` without any other `--save-*` flags implies save as dev. + #[inline(always)] + fn save_dev(&self) -> bool { + let &AddDependencyOptions { save_prod, save_dev, save_optional, save_peer } = self; + save_dev || (!save_prod && !save_optional && save_peer) + } + + /// Whether to add entry to `"optionalDependencies"`. + #[inline(always)] + pub fn save_optional(&self) -> bool { + self.save_optional + } + + /// Whether to add entry to `"peerDependencies"`. + #[inline(always)] + pub fn save_peer(&self) -> bool { + self.save_peer + } + /// Convert the `--save-*` flags to an iterator of [`DependencyGroup`] /// which selects which target group to save to. fn dependency_groups(&self) -> impl Iterator { - let &AddDependencyOptions { save_prod, save_dev, save_optional, save_peer } = self; - let has_prod = save_prod || (!save_dev && !save_optional && !save_peer); // no --save-* flags implies --save-prod - let has_dev = save_dev || (!save_prod && !save_optional && save_peer); // --save-peer with nothing else implies --save-dev - let has_optional = save_optional; - let has_peer = save_peer; std::iter::empty() - .chain(has_prod.then_some(DependencyGroup::Default)) - .chain(has_dev.then_some(DependencyGroup::Dev)) - .chain(has_optional.then_some(DependencyGroup::Optional)) - .chain(has_peer.then_some(DependencyGroup::Peer)) + .chain(self.save_prod().then_some(DependencyGroup::Default)) + .chain(self.save_dev().then_some(DependencyGroup::Dev)) + .chain(self.save_optional().then_some(DependencyGroup::Optional)) + .chain(self.save_peer().then_some(DependencyGroup::Peer)) } } From 11dfe1b5d3be2c43afc8f50fba23ecf8d4a9e83d Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 16 Oct 2023 13:20:39 +0700 Subject: [PATCH 188/210] refactor: remove unnecessary `pub` --- crates/cli/src/cli_args/add.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/cli/src/cli_args/add.rs b/crates/cli/src/cli_args/add.rs index b260cc45d..0c2df97fc 100644 --- a/crates/cli/src/cli_args/add.rs +++ b/crates/cli/src/cli_args/add.rs @@ -42,13 +42,13 @@ impl AddDependencyOptions { /// Whether to add entry to `"optionalDependencies"`. #[inline(always)] - pub fn save_optional(&self) -> bool { + fn save_optional(&self) -> bool { self.save_optional } /// Whether to add entry to `"peerDependencies"`. #[inline(always)] - pub fn save_peer(&self) -> bool { + fn save_peer(&self) -> bool { self.save_peer } From 0ad43b2f462aa146403c0cfe65ab68513cfbddd5 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 16 Oct 2023 13:22:13 +0700 Subject: [PATCH 189/210] refactor: remove unnecessary `pub` --- crates/cli/src/cli_args/install.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/cli/src/cli_args/install.rs b/crates/cli/src/cli_args/install.rs index ab9b2a879..d5ca17b59 100644 --- a/crates/cli/src/cli_args/install.rs +++ b/crates/cli/src/cli_args/install.rs @@ -10,14 +10,14 @@ pub struct InstallDependencyOptions { /// Use this flag to instruct pacquet to ignore NODE_ENV and take its production status from this /// flag instead. #[arg(short = 'P', long)] - pub prod: bool, + prod: bool, /// Only devDependencies are installed and dependencies are removed insofar they were /// already installed, regardless of the NODE_ENV. #[arg(short = 'D', long)] - pub dev: bool, + dev: bool, /// optionalDependencies are not installed. #[arg(long)] - pub no_optional: bool, + no_optional: bool, } impl InstallDependencyOptions { From 886f1d4a88c07fdf1ead393911ac7a10466cb3c1 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 16 Oct 2023 13:39:27 +0700 Subject: [PATCH 190/210] refactor: rename DependencyGroup::{Default -> Prod} --- crates/cli/src/cli_args/add.rs | 10 +++++----- crates/cli/src/cli_args/install.rs | 16 ++++++++-------- crates/cli/tests/add.rs | 2 +- crates/lockfile/src/project_snapshot.rs | 12 ++++++------ crates/package_json/src/lib.rs | 8 ++++---- crates/package_manager/src/install.rs | 4 ++-- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/crates/cli/src/cli_args/add.rs b/crates/cli/src/cli_args/add.rs index 0c2df97fc..eb7d62884 100644 --- a/crates/cli/src/cli_args/add.rs +++ b/crates/cli/src/cli_args/add.rs @@ -56,7 +56,7 @@ impl AddDependencyOptions { /// which selects which target group to save to. fn dependency_groups(&self) -> impl Iterator { std::iter::empty() - .chain(self.save_prod().then_some(DependencyGroup::Default)) + .chain(self.save_prod().then_some(DependencyGroup::Prod)) .chain(self.save_dev().then_some(DependencyGroup::Dev)) .chain(self.save_optional().then_some(DependencyGroup::Optional)) .chain(self.save_peer().then_some(DependencyGroup::Peer)) @@ -111,7 +111,7 @@ mod tests { #[test] fn dependency_options_to_dependency_groups() { - use DependencyGroup::{Default, Dev, Optional, Peer}; + use DependencyGroup::{Dev, Optional, Peer, Prod}; let create_list = |opts: AddDependencyOptions| opts.dependency_groups().collect::>(); // no flags -> prod @@ -122,7 +122,7 @@ mod tests { save_optional: false, save_peer: false }), - [Default] + [Prod] ); // --save-prod -> prod @@ -133,7 +133,7 @@ mod tests { save_optional: false, save_peer: false }), - [Default] + [Prod] ); // --save-dev -> dev @@ -177,7 +177,7 @@ mod tests { save_optional: false, save_peer: true }), - [Default, Peer] + [Prod, Peer] ); // --save-dev --save-peer -> dev + peer diff --git a/crates/cli/src/cli_args/install.rs b/crates/cli/src/cli_args/install.rs index d5ca17b59..b28f0a6be 100644 --- a/crates/cli/src/cli_args/install.rs +++ b/crates/cli/src/cli_args/install.rs @@ -30,7 +30,7 @@ impl InstallDependencyOptions { let has_dev = has_both || dev; let has_optional = !no_optional; std::iter::empty() - .chain(has_prod.then_some(DependencyGroup::Default)) + .chain(has_prod.then_some(DependencyGroup::Prod)) .chain(has_dev.then_some(DependencyGroup::Dev)) .chain(has_optional.then_some(DependencyGroup::Optional)) } @@ -76,20 +76,20 @@ mod tests { #[test] fn dependency_options_to_dependency_groups() { - use DependencyGroup::{Default, Dev, Optional}; + use DependencyGroup::{Dev, Optional, Prod}; let create_list = |opts: InstallDependencyOptions| opts.dependency_groups().collect::>(); // no flags -> prod + dev + optional assert_eq!( create_list(InstallDependencyOptions { prod: false, dev: false, no_optional: false }), - [Default, Dev, Optional], + [Prod, Dev, Optional], ); // --prod -> prod + optional assert_eq!( create_list(InstallDependencyOptions { prod: true, dev: false, no_optional: false }), - [Default, Optional], + [Prod, Optional], ); // --dev -> dev + optional @@ -101,13 +101,13 @@ mod tests { // --no-optional -> prod + dev assert_eq!( create_list(InstallDependencyOptions { prod: false, dev: false, no_optional: true }), - [Default, Dev], + [Prod, Dev], ); // --prod --no-optional -> prod assert_eq!( create_list(InstallDependencyOptions { prod: true, dev: false, no_optional: true }), - [Default], + [Prod], ); // --dev --no-optional -> dev @@ -119,13 +119,13 @@ mod tests { // --prod --dev -> prod + dev + optional assert_eq!( create_list(InstallDependencyOptions { prod: true, dev: true, no_optional: false }), - [Default, Dev, Optional], + [Prod, Dev, Optional], ); // --prod --dev --no-optional -> prod + dev assert_eq!( create_list(InstallDependencyOptions { prod: true, dev: true, no_optional: true }), - [Default, Dev], + [Prod, Dev], ); } } diff --git a/crates/cli/tests/add.rs b/crates/cli/tests/add.rs index 86380db25..3e653f719 100644 --- a/crates/cli/tests/add.rs +++ b/crates/cli/tests/add.rs @@ -66,7 +66,7 @@ fn should_add_to_package_json() { let dir = exec_pacquet_in_temp_cwd(["add", "is-odd"]); let file = PackageJson::from_path(dir.path().join("package.json")).unwrap(); eprintln!("Ensure is-odd is added to package.json#dependencies"); - assert!(file.dependencies([DependencyGroup::Default]).any(|(k, _)| k == "is-odd")); + assert!(file.dependencies([DependencyGroup::Prod]).any(|(k, _)| k == "is-odd")); } #[test] diff --git a/crates/lockfile/src/project_snapshot.rs b/crates/lockfile/src/project_snapshot.rs index ab17e0b1a..b68218b34 100644 --- a/crates/lockfile/src/project_snapshot.rs +++ b/crates/lockfile/src/project_snapshot.rs @@ -25,7 +25,7 @@ impl ProjectSnapshot { /// Lookup dependency map according to group. pub fn get_map_by_group(&self, group: DependencyGroup) -> Option<&'_ ResolvedDependencyMap> { match group { - DependencyGroup::Default => self.dependencies.as_ref(), + DependencyGroup::Prod => self.dependencies.as_ref(), DependencyGroup::Optional => self.optional_dependencies.as_ref(), DependencyGroup::Dev => self.dev_dependencies.as_ref(), DependencyGroup::Peer => None, @@ -74,7 +74,7 @@ mod tests { #[test] fn dependencies_by_groups() { - use DependencyGroup::{Default, Dev, Optional, Peer}; + use DependencyGroup::{Dev, Optional, Peer, Prod}; macro_rules! case { ($input:expr => $output:expr) => {{ @@ -95,7 +95,7 @@ mod tests { } case!([] => []); - case!([Default] => [ + case!([Prod] => [ ("react", "^17.0.2", "17.0.2"), ("react-dom", "^17.0.2", "17.0.2(react@17.0.2)"), ]); @@ -107,16 +107,16 @@ mod tests { ("ts-node", "10.9.1", "10.9.1(@types/node@18.7.19)(typescript@5.1.6)"), ("typescript", "^5.1.6", "5.1.6"), ]); - case!([Default, Peer] => [ + case!([Prod, Peer] => [ ("react", "^17.0.2", "17.0.2"), ("react-dom", "^17.0.2", "17.0.2(react@17.0.2)"), ]); - case!([Default, Peer, Optional] => [ + case!([Prod, Peer, Optional] => [ ("@types/node", "^18.7.19", "18.7.19"), ("react", "^17.0.2", "17.0.2"), ("react-dom", "^17.0.2", "17.0.2(react@17.0.2)"), ]); - case!([Default, Peer, Optional, Dev] => [ + case!([Prod, Peer, Optional, Dev] => [ ("@types/node", "^18.7.19", "18.7.19"), ("react", "^17.0.2", "17.0.2"), ("react-dom", "^17.0.2", "17.0.2(react@17.0.2)"), diff --git a/crates/package_json/src/lib.rs b/crates/package_json/src/lib.rs index 4cc3f1d43..c5c736f60 100644 --- a/crates/package_json/src/lib.rs +++ b/crates/package_json/src/lib.rs @@ -45,7 +45,7 @@ pub enum PackageJsonError { #[derive(Debug, Clone, Copy, PartialEq, IntoStaticStr)] pub enum DependencyGroup { #[strum(serialize = "dependencies")] - Default, + Prod, #[strum(serialize = "devDependencies")] Dev, #[strum(serialize = "optionalDependencies")] @@ -250,10 +250,10 @@ mod tests { let dir = tempdir().unwrap(); let tmp = dir.path().join("package.json"); let mut package_json = PackageJson::create_if_needed(tmp.clone()).unwrap(); - package_json.add_dependency("fastify", "1.0.0", DependencyGroup::Default).unwrap(); + package_json.add_dependency("fastify", "1.0.0", DependencyGroup::Prod).unwrap(); let dependencies: HashMap<_, _> = - package_json.dependencies([DependencyGroup::Default]).collect(); + package_json.dependencies([DependencyGroup::Prod]).collect(); assert!(dependencies.contains_key("fastify")); assert_eq!(dependencies.get("fastify").unwrap(), &"1.0.0"); package_json.save().unwrap(); @@ -302,7 +302,7 @@ mod tests { let package_json = PackageJson::create_if_needed(tmp.path().to_path_buf()).unwrap(); let dependencies = |groups| package_json.dependencies(groups).collect::>(); assert!(dependencies([DependencyGroup::Peer]).contains_key("fast-querystring")); - assert!(dependencies([DependencyGroup::Default]).contains_key("fastify")); + assert!(dependencies([DependencyGroup::Prod]).contains_key("fastify")); } #[test] diff --git a/crates/package_manager/src/install.rs b/crates/package_manager/src/install.rs index 90cffc670..46e4f5520 100644 --- a/crates/package_manager/src/install.rs +++ b/crates/package_manager/src/install.rs @@ -101,7 +101,7 @@ mod tests { let package_json_path = dir.path().join("package.json"); let mut package_json = PackageJson::create_if_needed(package_json_path.clone()).unwrap(); - package_json.add_dependency("is-odd", "3.0.1", DependencyGroup::Default).unwrap(); + package_json.add_dependency("is-odd", "3.0.1", DependencyGroup::Prod).unwrap(); package_json .add_dependency("fast-decode-uri-component", "1.0.1", DependencyGroup::Dev) .unwrap(); @@ -121,7 +121,7 @@ mod tests { package_json: &package_json, lockfile: None, dependency_groups: [ - DependencyGroup::Default, + DependencyGroup::Prod, DependencyGroup::Dev, DependencyGroup::Optional, ], From 1aee2a377e9f53026280e3838253a808c044a1d8 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 16 Oct 2023 13:47:20 +0700 Subject: [PATCH 191/210] docs: future plan --- crates/package_manager/src/add.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/package_manager/src/add.rs b/crates/package_manager/src/add.rs index 2936ee627..8a6a043ce 100644 --- a/crates/package_manager/src/add.rs +++ b/crates/package_manager/src/add.rs @@ -31,7 +31,7 @@ where /// Name of the package to add. pub package: &'a str, /// Whether `--save-exact` is provided. - pub save_exact: bool, + pub save_exact: bool, // TODO: add `save-exact` to `.npmrc`, merge configs, and remove this } /// Error type of [`Add`]. From ea79141ef7d971e9b4aa97488fe967b0b199fff0 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 16 Oct 2023 13:50:05 +0700 Subject: [PATCH 192/210] docs: list_dependency_groups --- crates/package_manager/src/add.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/package_manager/src/add.rs b/crates/package_manager/src/add.rs index 8a6a043ce..1ef8239bd 100644 --- a/crates/package_manager/src/add.rs +++ b/crates/package_manager/src/add.rs @@ -26,7 +26,7 @@ where pub package_json: &'a mut PackageJson, /// Data from the `pnpm-lock.yaml` file. pub lockfile: Option<&'a Lockfile>, - /// List of [`DependencyGroup`]s. + /// Function that creates an iterator [`DependencyGroup`]s. pub list_dependency_groups: ListDependencyGroups, /// Name of the package to add. pub package: &'a str, From e877d1d233430a0d68cfe1056a0e2a37f3bf284a Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 16 Oct 2023 13:50:26 +0700 Subject: [PATCH 193/210] docs: why it is that way it is --- crates/package_manager/src/add.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/package_manager/src/add.rs b/crates/package_manager/src/add.rs index 1ef8239bd..ed749144d 100644 --- a/crates/package_manager/src/add.rs +++ b/crates/package_manager/src/add.rs @@ -27,7 +27,7 @@ where /// Data from the `pnpm-lock.yaml` file. pub lockfile: Option<&'a Lockfile>, /// Function that creates an iterator [`DependencyGroup`]s. - pub list_dependency_groups: ListDependencyGroups, + pub list_dependency_groups: ListDependencyGroups, // must be a function because it is called multiple times /// Name of the package to add. pub package: &'a str, /// Whether `--save-exact` is provided. From 86b52d9fc4b8c10fe57aecdf2ccc8be6bcc140cf Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 16 Oct 2023 13:57:54 +0700 Subject: [PATCH 194/210] docs: future plan --- crates/package_json/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/package_json/src/lib.rs b/crates/package_json/src/lib.rs index c5c736f60..7d739f37f 100644 --- a/crates/package_json/src/lib.rs +++ b/crates/package_json/src/lib.rs @@ -63,7 +63,7 @@ pub enum BundleDependencies { pub struct PackageJson { path: PathBuf, - value: Value, + value: Value, // TODO: convert this into a proper struct + an array of keys order } impl PackageJson { From 5f953bb3ad259155b51681b1d1690904b7b2c2e8 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 16 Oct 2023 14:05:02 +0700 Subject: [PATCH 195/210] refactor: rename PackageJson to PackageManifest --- Cargo.lock | 36 ++++++------- Cargo.toml | 24 ++++----- crates/cli/Cargo.toml | 20 +++---- crates/cli/src/cli_args.rs | 8 +-- crates/cli/src/cli_args/add.rs | 4 +- crates/cli/src/cli_args/install.rs | 4 +- crates/cli/src/cli_args/run.rs | 4 +- crates/cli/src/state.rs | 6 +-- crates/cli/tests/add.rs | 8 +-- .../init__should_throw_on_existing_file.snap | 4 +- crates/lockfile/Cargo.toml | 4 +- crates/lockfile/src/project_snapshot.rs | 2 +- crates/package_manager/Cargo.toml | 12 ++--- crates/package_manager/src/add.rs | 6 +-- crates/package_manager/src/install.rs | 9 ++-- .../src/install_frozen_lockfile.rs | 2 +- .../src/install_without_lockfile.rs | 4 +- .../src/symlink_direct_dependencies.rs | 2 +- .../Cargo.toml | 2 +- .../src/lib.rs | 53 ++++++++++--------- ...st__tests__init_package_json_content.snap} | 1 + 21 files changed, 109 insertions(+), 106 deletions(-) rename crates/{package_json => package_manifest}/Cargo.toml (92%) rename crates/{package_json => package_manifest}/src/lib.rs (84%) rename crates/{package_json/src/snapshots/pacquet_package_json__tests__init_package_json_content.snap => package_manifest/src/snapshots/pacquet_package_manifest__tests__init_package_json_content.snap} (94%) diff --git a/Cargo.lock b/Cargo.lock index ecd268485..1c6967661 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1326,8 +1326,8 @@ dependencies = [ "pacquet_fs", "pacquet_lockfile", "pacquet_npmrc", - "pacquet_package_json", "pacquet_package_manager", + "pacquet_package_manifest", "pacquet_registry", "pacquet_tarball", "pacquet_testing_utils", @@ -1383,7 +1383,7 @@ dependencies = [ "derive_more", "node-semver", "pacquet_diagnostics", - "pacquet_package_json", + "pacquet_package_manifest", "pipe-trait", "pretty_assertions", "serde", @@ -1421,21 +1421,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "pacquet_package_json" -version = "0.0.1" -dependencies = [ - "derive_more", - "insta", - "miette", - "pipe-trait", - "pretty_assertions", - "serde", - "serde_json", - "strum", - "tempfile", -] - [[package]] name = "pacquet_package_manager" version = "0.0.1" @@ -1449,7 +1434,7 @@ dependencies = [ "pacquet_fs", "pacquet_lockfile", "pacquet_npmrc", - "pacquet_package_json", + "pacquet_package_manifest", "pacquet_registry", "pacquet_tarball", "pacquet_testing_utils", @@ -1464,6 +1449,21 @@ dependencies = [ "walkdir", ] +[[package]] +name = "pacquet_package_manifest" +version = "0.0.1" +dependencies = [ + "derive_more", + "insta", + "miette", + "pipe-trait", + "pretty_assertions", + "serde", + "serde_json", + "strum", + "tempfile", +] + [[package]] name = "pacquet_registry" version = "0.0.1" diff --git a/Cargo.toml b/Cargo.toml index 8f0e2152e..411dfcee6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,18 +13,18 @@ repository = "https://github.com/anonrig/pacquet" [workspace.dependencies] # Crates -pacquet_cli = { path = "crates/cli" } -pacquet_fs = { path = "crates/fs" } -pacquet_registry = { path = "crates/registry" } -pacquet_tarball = { path = "crates/tarball" } -pacquet_testing_utils = { path = "crates/testing-utils" } -pacquet_package_json = { path = "crates/package_json" } -pacquet_package_manager = { path = "crates/package_manager" } -pacquet_lockfile = { path = "crates/lockfile" } -pacquet_npmrc = { path = "crates/npmrc" } -pacquet_executor = { path = "crates/executor" } -pacquet_cafs = { path = "crates/cafs" } -pacquet_diagnostics = { path = "crates/diagnostics" } +pacquet_cli = { path = "crates/cli" } +pacquet_fs = { path = "crates/fs" } +pacquet_registry = { path = "crates/registry" } +pacquet_tarball = { path = "crates/tarball" } +pacquet_testing_utils = { path = "crates/testing-utils" } +pacquet_package_manifest = { path = "crates/package_manifest" } +pacquet_package_manager = { path = "crates/package_manager" } +pacquet_lockfile = { path = "crates/lockfile" } +pacquet_npmrc = { path = "crates/npmrc" } +pacquet_executor = { path = "crates/executor" } +pacquet_cafs = { path = "crates/cafs" } +pacquet_diagnostics = { path = "crates/diagnostics" } # Dependencies async-recursion = { version = "1.0.5" } diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 8452ee795..4b892f6b0 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -15,16 +15,16 @@ name = "pacquet" path = "src/bin/main.rs" [dependencies] -pacquet_cafs = { workspace = true } -pacquet_executor = { workspace = true } -pacquet_fs = { workspace = true } -pacquet_lockfile = { workspace = true } -pacquet_npmrc = { workspace = true } -pacquet_package_json = { workspace = true } -pacquet_package_manager = { workspace = true } -pacquet_registry = { workspace = true } -pacquet_tarball = { workspace = true } -pacquet_diagnostics = { workspace = true } +pacquet_cafs = { workspace = true } +pacquet_executor = { workspace = true } +pacquet_fs = { workspace = true } +pacquet_lockfile = { workspace = true } +pacquet_npmrc = { workspace = true } +pacquet_package_manifest = { workspace = true } +pacquet_package_manager = { workspace = true } +pacquet_registry = { workspace = true } +pacquet_tarball = { workspace = true } +pacquet_diagnostics = { workspace = true } clap = { workspace = true } derive_more = { workspace = true } diff --git a/crates/cli/src/cli_args.rs b/crates/cli/src/cli_args.rs index 9ec4e89db..c1881ea34 100644 --- a/crates/cli/src/cli_args.rs +++ b/crates/cli/src/cli_args.rs @@ -10,7 +10,7 @@ use install::InstallArgs; use miette::Context; use pacquet_executor::execute_shell; use pacquet_npmrc::Npmrc; -use pacquet_package_json::PackageJson; +use pacquet_package_manifest::PackageManifest; use run::RunArgs; use std::{env, path::PathBuf}; use store::StoreCommand; @@ -60,12 +60,12 @@ impl CliArgs { match command { CliCommand::Init => { // init command throws an error if package.json file exist. - PackageJson::init(&package_json_path()).wrap_err("initialize package.json")?; + PackageManifest::init(&package_json_path()).wrap_err("initialize package.json")?; } CliCommand::Add(args) => args.run(state()?).await?, CliCommand::Install(args) => args.run(state()?).await?, CliCommand::Test => { - let package_json = PackageJson::from_path(package_json_path()) + let package_json = PackageManifest::from_path(package_json_path()) .wrap_err("getting the package.json in current directory")?; if let Some(script) = package_json.script("test", false)? { execute_shell(script) @@ -78,7 +78,7 @@ impl CliArgs { // object. If no start property is specified on the scripts object, it will attempt to // run node server.js as a default, failing if neither are present. // The intended usage of the property is to specify a command that starts your program. - let package_json = PackageJson::from_path(package_json_path()) + let package_json = PackageManifest::from_path(package_json_path()) .wrap_err("getting the package.json in current directory")?; let command = if let Some(script) = package_json.script("start", true)? { script diff --git a/crates/cli/src/cli_args/add.rs b/crates/cli/src/cli_args/add.rs index eb7d62884..18f459232 100644 --- a/crates/cli/src/cli_args/add.rs +++ b/crates/cli/src/cli_args/add.rs @@ -1,8 +1,8 @@ use crate::State; use clap::Args; use miette::Context; -use pacquet_package_json::DependencyGroup; use pacquet_package_manager::Add; +use pacquet_package_manifest::DependencyGroup; use std::path::PathBuf; #[derive(Debug, Args)] @@ -106,7 +106,7 @@ impl AddArgs { #[cfg(test)] mod tests { use super::*; - use pacquet_package_json::DependencyGroup; + use pacquet_package_manifest::DependencyGroup; use pretty_assertions::assert_eq; #[test] diff --git a/crates/cli/src/cli_args/install.rs b/crates/cli/src/cli_args/install.rs index b28f0a6be..c0d29e867 100644 --- a/crates/cli/src/cli_args/install.rs +++ b/crates/cli/src/cli_args/install.rs @@ -1,7 +1,7 @@ use crate::State; use clap::Args; -use pacquet_package_json::DependencyGroup; use pacquet_package_manager::Install; +use pacquet_package_manifest::DependencyGroup; #[derive(Debug, Args)] pub struct InstallDependencyOptions { @@ -71,7 +71,7 @@ impl InstallArgs { #[cfg(test)] mod tests { use super::*; - use pacquet_package_json::DependencyGroup; + use pacquet_package_manifest::DependencyGroup; use pretty_assertions::assert_eq; #[test] diff --git a/crates/cli/src/cli_args/run.rs b/crates/cli/src/cli_args/run.rs index 817051f77..aa07cb7df 100644 --- a/crates/cli/src/cli_args/run.rs +++ b/crates/cli/src/cli_args/run.rs @@ -1,7 +1,7 @@ use clap::Args; use miette::Context; use pacquet_executor::execute_shell; -use pacquet_package_json::PackageJson; +use pacquet_package_manifest::PackageManifest; use std::path::PathBuf; #[derive(Debug, Args)] @@ -24,7 +24,7 @@ impl RunArgs { pub fn run(self, package_json_path: PathBuf) -> miette::Result<()> { let RunArgs { command, args, if_present } = self; - let package_json = PackageJson::from_path(package_json_path) + let package_json = PackageManifest::from_path(package_json_path) .wrap_err("getting the package.json in current directory")?; if let Some(script) = package_json.script(&command, if_present)? { diff --git a/crates/cli/src/state.rs b/crates/cli/src/state.rs index 13972f9c3..a09a3d7a1 100644 --- a/crates/cli/src/state.rs +++ b/crates/cli/src/state.rs @@ -2,7 +2,7 @@ use derive_more::{Display, Error}; use miette::Diagnostic; use pacquet_lockfile::{LoadLockfileError, Lockfile}; use pacquet_npmrc::Npmrc; -use pacquet_package_json::{PackageJson, PackageJsonError}; +use pacquet_package_manifest::{PackageJsonError, PackageManifest}; use pacquet_tarball::Cache; use pipe_trait::Pipe; use reqwest::Client; @@ -17,7 +17,7 @@ pub struct State { /// Configuration read from `.npmrc` pub config: &'static Npmrc, /// Data from the `package.json` file. - pub package_json: PackageJson, + pub package_json: PackageManifest, /// Data from the `pnpm-lock.yaml` file. pub lockfile: Option, } @@ -42,7 +42,7 @@ impl State { Ok(State { config, package_json: package_json_path - .pipe(PackageJson::create_if_needed) + .pipe(PackageManifest::create_if_needed) .map_err(InitStateError::LoadPackageJson)?, lockfile: call_load_lockfile(config.lockfile, Lockfile::load_from_current_dir) .map_err(InitStateError::LoadLockfile)?, diff --git a/crates/cli/tests/add.rs b/crates/cli/tests/add.rs index 3e653f719..eb65560e8 100644 --- a/crates/cli/tests/add.rs +++ b/crates/cli/tests/add.rs @@ -1,7 +1,7 @@ pub mod _utils; pub use _utils::*; -use pacquet_package_json::{DependencyGroup, PackageJson}; +use pacquet_package_manifest::{DependencyGroup, PackageManifest}; use pacquet_testing_utils::fs::{get_all_folders, get_filenames_in_folder}; use pretty_assertions::assert_eq; use std::{env, fs}; @@ -64,7 +64,7 @@ pub fn should_symlink_correctly() { #[test] fn should_add_to_package_json() { let dir = exec_pacquet_in_temp_cwd(["add", "is-odd"]); - let file = PackageJson::from_path(dir.path().join("package.json")).unwrap(); + let file = PackageManifest::from_path(dir.path().join("package.json")).unwrap(); eprintln!("Ensure is-odd is added to package.json#dependencies"); assert!(file.dependencies([DependencyGroup::Prod]).any(|(k, _)| k == "is-odd")); } @@ -72,7 +72,7 @@ fn should_add_to_package_json() { #[test] fn should_add_dev_dependency() { let dir = exec_pacquet_in_temp_cwd(["add", "is-odd", "--save-dev"]); - let file = PackageJson::from_path(dir.path().join("package.json")).unwrap(); + let file = PackageManifest::from_path(dir.path().join("package.json")).unwrap(); eprintln!("Ensure is-odd is added to package.json#devDependencies"); assert!(file.dependencies([DependencyGroup::Dev]).any(|(k, _)| k == "is-odd")); } @@ -80,7 +80,7 @@ fn should_add_dev_dependency() { #[test] fn should_add_peer_dependency() { let dir = exec_pacquet_in_temp_cwd(["add", "is-odd", "--save-peer"]); - let file = PackageJson::from_path(dir.path().join("package.json")).unwrap(); + let file = PackageManifest::from_path(dir.path().join("package.json")).unwrap(); eprintln!("Ensure is-odd is added to package.json#devDependencies"); assert!(file.dependencies([DependencyGroup::Dev]).any(|(k, _)| k == "is-odd")); eprintln!("Ensure is-odd is added to package.json#peerDependencies"); diff --git a/crates/cli/tests/snapshots/init__should_throw_on_existing_file.snap b/crates/cli/tests/snapshots/init__should_throw_on_existing_file.snap index 99bad67dc..e35b51a82 100644 --- a/crates/cli/tests/snapshots/init__should_throw_on_existing_file.snap +++ b/crates/cli/tests/snapshots/init__should_throw_on_existing_file.snap @@ -1,9 +1,9 @@ --- source: crates/cli/tests/init.rs -assertion_line: 56 +assertion_line: 43 expression: "String::from_utf8_lossy(&output.stderr).trim_end()" --- -Error: pacquet_package_json::already_exist_error +Error: pacquet_package_manifest::already_exist_error × initialize package.json ╰─▶ package.json file already exists diff --git a/crates/lockfile/Cargo.toml b/crates/lockfile/Cargo.toml index 992e4b874..b1e44fe59 100644 --- a/crates/lockfile/Cargo.toml +++ b/crates/lockfile/Cargo.toml @@ -11,8 +11,8 @@ license.workspace = true repository.workspace = true [dependencies] -pacquet_diagnostics = { workspace = true } -pacquet_package_json = { workspace = true } +pacquet_diagnostics = { workspace = true } +pacquet_package_manifest = { workspace = true } derive_more = { workspace = true } node-semver = { workspace = true } diff --git a/crates/lockfile/src/project_snapshot.rs b/crates/lockfile/src/project_snapshot.rs index b68218b34..690b6ebe7 100644 --- a/crates/lockfile/src/project_snapshot.rs +++ b/crates/lockfile/src/project_snapshot.rs @@ -1,5 +1,5 @@ use crate::{PkgName, ResolvedDependencyMap, ResolvedDependencySpec}; -use pacquet_package_json::DependencyGroup; +use pacquet_package_manifest::DependencyGroup; use serde::{Deserialize, Serialize}; use std::collections::HashMap; diff --git a/crates/package_manager/Cargo.toml b/crates/package_manager/Cargo.toml index e1afd8a46..60b463acd 100644 --- a/crates/package_manager/Cargo.toml +++ b/crates/package_manager/Cargo.toml @@ -11,12 +11,12 @@ license.workspace = true repository.workspace = true [dependencies] -pacquet_fs = { workspace = true } -pacquet_lockfile = { workspace = true } -pacquet_npmrc = { workspace = true } -pacquet_package_json = { workspace = true } -pacquet_registry = { workspace = true } -pacquet_tarball = { workspace = true } +pacquet_fs = { workspace = true } +pacquet_lockfile = { workspace = true } +pacquet_npmrc = { workspace = true } +pacquet_package_manifest = { workspace = true } +pacquet_registry = { workspace = true } +pacquet_tarball = { workspace = true } async-recursion = { workspace = true } derive_more = { workspace = true } diff --git a/crates/package_manager/src/add.rs b/crates/package_manager/src/add.rs index ed749144d..0bcad3015 100644 --- a/crates/package_manager/src/add.rs +++ b/crates/package_manager/src/add.rs @@ -3,8 +3,8 @@ use derive_more::{Display, Error}; use miette::Diagnostic; use pacquet_lockfile::Lockfile; use pacquet_npmrc::Npmrc; -use pacquet_package_json::PackageJsonError; -use pacquet_package_json::{DependencyGroup, PackageJson}; +use pacquet_package_manifest::PackageJsonError; +use pacquet_package_manifest::{DependencyGroup, PackageManifest}; use pacquet_registry::{PackageTag, PackageVersion}; use pacquet_tarball::Cache; use reqwest::Client; @@ -23,7 +23,7 @@ where /// Configuration read from `.npmrc`. pub config: &'static Npmrc, /// Data from the `package.json` file. - pub package_json: &'a mut PackageJson, + pub package_json: &'a mut PackageManifest, /// Data from the `pnpm-lock.yaml` file. pub lockfile: Option<&'a Lockfile>, /// Function that creates an iterator [`DependencyGroup`]s. diff --git a/crates/package_manager/src/install.rs b/crates/package_manager/src/install.rs index 46e4f5520..dbcee3580 100644 --- a/crates/package_manager/src/install.rs +++ b/crates/package_manager/src/install.rs @@ -1,7 +1,7 @@ use crate::{InstallFrozenLockfile, InstallWithoutLockfile}; use pacquet_lockfile::Lockfile; use pacquet_npmrc::Npmrc; -use pacquet_package_json::{DependencyGroup, PackageJson}; +use pacquet_package_manifest::{DependencyGroup, PackageManifest}; use pacquet_tarball::Cache; use reqwest::Client; @@ -18,7 +18,7 @@ where /// Configuration read from `.npmrc`. pub config: &'static Npmrc, /// Data from the `package.json` file. - pub package_json: &'a PackageJson, + pub package_json: &'a PackageManifest, /// Data from the `pnpm-lock.yaml` file. pub lockfile: Option<&'a Lockfile>, /// List of [`DependencyGroup`]s. @@ -85,7 +85,7 @@ where mod tests { use super::*; use pacquet_npmrc::Npmrc; - use pacquet_package_json::{DependencyGroup, PackageJson}; + use pacquet_package_manifest::{DependencyGroup, PackageManifest}; use pacquet_testing_utils::fs::{get_all_folders, is_symlink_or_junction}; use std::env; use tempfile::tempdir; @@ -99,7 +99,8 @@ mod tests { let virtual_store_dir = modules_dir.join(".pacquet"); // TODO: we shouldn't have to define this let package_json_path = dir.path().join("package.json"); - let mut package_json = PackageJson::create_if_needed(package_json_path.clone()).unwrap(); + let mut package_json = + PackageManifest::create_if_needed(package_json_path.clone()).unwrap(); package_json.add_dependency("is-odd", "3.0.1", DependencyGroup::Prod).unwrap(); package_json diff --git a/crates/package_manager/src/install_frozen_lockfile.rs b/crates/package_manager/src/install_frozen_lockfile.rs index 5c710b23a..d5c745827 100644 --- a/crates/package_manager/src/install_frozen_lockfile.rs +++ b/crates/package_manager/src/install_frozen_lockfile.rs @@ -1,7 +1,7 @@ use crate::{CreateVirtualStore, SymlinkDirectDependencies}; use pacquet_lockfile::{DependencyPath, PackageSnapshot, RootProjectSnapshot}; use pacquet_npmrc::Npmrc; -use pacquet_package_json::DependencyGroup; +use pacquet_package_manifest::DependencyGroup; use pacquet_tarball::Cache; use reqwest::Client; use std::collections::HashMap; diff --git a/crates/package_manager/src/install_without_lockfile.rs b/crates/package_manager/src/install_without_lockfile.rs index 806c96e8d..ce1b59fe1 100644 --- a/crates/package_manager/src/install_without_lockfile.rs +++ b/crates/package_manager/src/install_without_lockfile.rs @@ -3,7 +3,7 @@ use async_recursion::async_recursion; use futures_util::future; use node_semver::Version; use pacquet_npmrc::Npmrc; -use pacquet_package_json::{DependencyGroup, PackageJson}; +use pacquet_package_manifest::{DependencyGroup, PackageManifest}; use pacquet_registry::PackageVersion; use pacquet_tarball::Cache; use pipe_trait::Pipe; @@ -27,7 +27,7 @@ pub struct InstallWithoutLockfile<'a, DependencyGroupList> { /// Configuration read from `.npmrc`. pub config: &'static Npmrc, /// Data from the `package.json` file. - pub package_json: &'a PackageJson, + pub package_json: &'a PackageManifest, /// List of [`DependencyGroup`]s. pub dependency_groups: DependencyGroupList, } diff --git a/crates/package_manager/src/symlink_direct_dependencies.rs b/crates/package_manager/src/symlink_direct_dependencies.rs index b9d42837b..2a5ebb305 100644 --- a/crates/package_manager/src/symlink_direct_dependencies.rs +++ b/crates/package_manager/src/symlink_direct_dependencies.rs @@ -1,7 +1,7 @@ use crate::symlink_package; use pacquet_lockfile::{PkgName, PkgNameVerPeer, RootProjectSnapshot}; use pacquet_npmrc::Npmrc; -use pacquet_package_json::DependencyGroup; +use pacquet_package_manifest::DependencyGroup; use rayon::prelude::*; /// This subroutine creates symbolic links in the `node_modules` directory for diff --git a/crates/package_json/Cargo.toml b/crates/package_manifest/Cargo.toml similarity index 92% rename from crates/package_json/Cargo.toml rename to crates/package_manifest/Cargo.toml index dc058209c..d73e4eec3 100644 --- a/crates/package_json/Cargo.toml +++ b/crates/package_manifest/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pacquet_package_json" +name = "pacquet_package_manifest" version = "0.0.1" publish = false authors.workspace = true diff --git a/crates/package_json/src/lib.rs b/crates/package_manifest/src/lib.rs similarity index 84% rename from crates/package_json/src/lib.rs rename to crates/package_manifest/src/lib.rs index 7d739f37f..2d6afdff0 100644 --- a/crates/package_json/src/lib.rs +++ b/crates/package_manifest/src/lib.rs @@ -13,32 +13,32 @@ use strum::IntoStaticStr; #[derive(Debug, Display, Error, From, Diagnostic)] #[non_exhaustive] pub enum PackageJsonError { - #[diagnostic(code(pacquet_package_json::serialization_error))] + #[diagnostic(code(pacquet_package_manifest::serialization_error))] Serialization(serde_json::Error), // TODO: remove derive(From), split this variant - #[diagnostic(code(pacquet_package_json::io_error))] + #[diagnostic(code(pacquet_package_manifest::io_error))] Io(std::io::Error), // TODO: remove derive(From), split this variant #[display("package.json file already exists")] #[diagnostic( - code(pacquet_package_json::already_exist_error), + code(pacquet_package_manifest::already_exist_error), help("Your current working directory already has a package.json file.") )] AlreadyExist, #[from(ignore)] // TODO: remove this after derive(From) has been removed #[display("invalid attribute: {_0}")] - #[diagnostic(code(pacquet_package_json::invalid_attribute))] + #[diagnostic(code(pacquet_package_manifest::invalid_attribute))] InvalidAttribute(#[error(not(source))] String), #[from(ignore)] // TODO: remove this after derive(From) has been removed #[display("No package.json was found in {_0}")] - #[diagnostic(code(pacquet_package_json::no_import_manifest_found))] + #[diagnostic(code(pacquet_package_manifest::no_import_manifest_found))] NoImporterManifestFound(#[error(not(source))] String), #[from(ignore)] // TODO: remove this after derive(From) has been removed #[display("Missing script: {_0:?}")] - #[diagnostic(code(pacquet_package_json::no_script_error))] + #[diagnostic(code(pacquet_package_manifest::no_script_error))] NoScript(#[error(not(source))] String), } @@ -61,12 +61,12 @@ pub enum BundleDependencies { List(Vec), } -pub struct PackageJson { +pub struct PackageManifest { path: PathBuf, value: Value, // TODO: convert this into a proper struct + an array of keys order } -impl PackageJson { +impl PackageManifest { fn create_init_package_json(name: &str) -> Value { json!({ "name": name, @@ -88,7 +88,7 @@ impl PackageJson { .and_then(|folder| folder.file_name()) .and_then(|file_name| file_name.to_str()) .unwrap_or(""); - let package_json = PackageJson::create_init_package_json(name); + let package_json = PackageManifest::create_init_package_json(name); let contents = serde_json::to_string_pretty(&package_json)?; fs::write(path, &contents)?; // TODO: forbid overwriting existing files Ok((package_json, contents)) @@ -103,28 +103,28 @@ impl PackageJson { if path.exists() { return Err(PackageJsonError::AlreadyExist); } - let (_, contents) = PackageJson::write_to_file(path)?; + let (_, contents) = PackageManifest::write_to_file(path)?; println!("Wrote to {path}\n\n{contents}", path = path.display()); Ok(()) } - pub fn from_path(path: PathBuf) -> Result { + pub fn from_path(path: PathBuf) -> Result { if !path.exists() { return Err(PackageJsonError::NoImporterManifestFound(path.display().to_string())); } - let value = PackageJson::read_from_file(&path)?; - Ok(PackageJson { path, value }) + let value = PackageManifest::read_from_file(&path)?; + Ok(PackageManifest { path, value }) } - pub fn create_if_needed(path: PathBuf) -> Result { + pub fn create_if_needed(path: PathBuf) -> Result { let value = if path.exists() { - PackageJson::read_from_file(&path)? + PackageManifest::read_from_file(&path)? } else { - PackageJson::write_to_file(&path).map(|(value, _)| value)? + PackageManifest::write_to_file(&path).map(|(value, _)| value)? }; - Ok(PackageJson { path, value }) + Ok(PackageManifest { path, value }) } pub fn path(&self) -> &'_ Path { @@ -224,7 +224,7 @@ mod tests { #[test] fn test_init_package_json_content() { - let package_json = PackageJson::create_init_package_json("test"); + let package_json = PackageManifest::create_init_package_json("test"); assert_snapshot!(serde_json::to_string_pretty(&package_json).unwrap()); } @@ -232,24 +232,24 @@ mod tests { fn init_should_throw_if_exists() { let tmp = NamedTempFile::new().unwrap(); write!(tmp.as_file(), "hello world").unwrap(); - PackageJson::init(tmp.path()).expect_err("package.json already exist"); + PackageManifest::init(tmp.path()).expect_err("package.json already exist"); } #[test] fn init_should_create_package_json_if_not_exist() { let dir = tempdir().unwrap(); let tmp = dir.path().join("package.json"); - PackageJson::init(&tmp).unwrap(); + PackageManifest::init(&tmp).unwrap(); assert!(tmp.exists()); assert!(tmp.is_file()); - assert_eq!(PackageJson::from_path(tmp.clone()).unwrap().path, tmp); + assert_eq!(PackageManifest::from_path(tmp.clone()).unwrap().path, tmp); } #[test] fn should_add_dependency() { let dir = tempdir().unwrap(); let tmp = dir.path().join("package.json"); - let mut package_json = PackageJson::create_if_needed(tmp.clone()).unwrap(); + let mut package_json = PackageManifest::create_if_needed(tmp.clone()).unwrap(); package_json.add_dependency("fastify", "1.0.0", DependencyGroup::Prod).unwrap(); let dependencies: HashMap<_, _> = @@ -264,7 +264,7 @@ mod tests { fn should_throw_on_missing_command() { let dir = tempdir().unwrap(); let tmp = dir.path().join("package.json"); - let package_json = PackageJson::create_if_needed(tmp).unwrap(); + let package_json = PackageManifest::create_if_needed(tmp).unwrap(); package_json.script("dev", false).expect_err("dev command should not exist"); } @@ -279,7 +279,7 @@ mod tests { "#; let tmp = NamedTempFile::new().unwrap(); write!(tmp.as_file(), "{}", data).unwrap(); - let package_json = PackageJson::create_if_needed(tmp.path().to_path_buf()).unwrap(); + let package_json = PackageManifest::create_if_needed(tmp.path().to_path_buf()).unwrap(); package_json.script("test", false).unwrap(); package_json.script("invalid", false).expect_err("invalid command should not exist"); package_json.script("invalid", true).unwrap(); @@ -299,7 +299,7 @@ mod tests { "#; let tmp = NamedTempFile::new().unwrap(); write!(tmp.as_file(), "{}", data).unwrap(); - let package_json = PackageJson::create_if_needed(tmp.path().to_path_buf()).unwrap(); + let package_json = PackageManifest::create_if_needed(tmp.path().to_path_buf()).unwrap(); let dependencies = |groups| package_json.dependencies(groups).collect::>(); assert!(dependencies([DependencyGroup::Peer]).contains_key("fast-querystring")); assert!(dependencies([DependencyGroup::Prod]).contains_key("fastify")); @@ -321,7 +321,8 @@ mod tests { eprintln!("CASE: {data}"); let tmp = NamedTempFile::new().unwrap(); write!(tmp.as_file(), "{}", data).unwrap(); - let package_json = PackageJson::create_if_needed(tmp.path().to_path_buf()).unwrap(); + let package_json = + PackageManifest::create_if_needed(tmp.path().to_path_buf()).unwrap(); let bundle = package_json.bundle_dependencies().unwrap(); assert_eq!(bundle, $output); }}; diff --git a/crates/package_json/src/snapshots/pacquet_package_json__tests__init_package_json_content.snap b/crates/package_manifest/src/snapshots/pacquet_package_manifest__tests__init_package_json_content.snap similarity index 94% rename from crates/package_json/src/snapshots/pacquet_package_json__tests__init_package_json_content.snap rename to crates/package_manifest/src/snapshots/pacquet_package_manifest__tests__init_package_json_content.snap index 9bf9909e0..3d813d77d 100644 --- a/crates/package_json/src/snapshots/pacquet_package_json__tests__init_package_json_content.snap +++ b/crates/package_manifest/src/snapshots/pacquet_package_manifest__tests__init_package_json_content.snap @@ -1,5 +1,6 @@ --- source: crates/package_json/src/lib.rs +assertion_line: 228 expression: "serde_json::to_string_pretty(&package_json).unwrap()" --- { From de034f96c91037661d02feea6287c2b3274a30bb Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 16 Oct 2023 14:10:47 +0700 Subject: [PATCH 196/210] docs: PackageManifest --- crates/package_manifest/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/package_manifest/src/lib.rs b/crates/package_manifest/src/lib.rs index 2d6afdff0..1269e8185 100644 --- a/crates/package_manifest/src/lib.rs +++ b/crates/package_manifest/src/lib.rs @@ -61,6 +61,7 @@ pub enum BundleDependencies { List(Vec), } +/// Content of the `package.json` files and its path. pub struct PackageManifest { path: PathBuf, value: Value, // TODO: convert this into a proper struct + an array of keys order From a04e42ea3fe3ef8d823b92739c7aec43cfb813be Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 16 Oct 2023 14:17:44 +0700 Subject: [PATCH 197/210] refactor: rename fields and variables --- crates/cli/src/cli_args.rs | 16 ++++---- crates/cli/src/cli_args/add.rs | 4 +- crates/cli/src/cli_args/install.rs | 4 +- crates/cli/src/cli_args/run.rs | 6 +-- crates/cli/src/state.rs | 9 ++--- crates/cli/tests/add.rs | 12 +++--- crates/cli/tests/init.rs | 12 +++--- crates/cli/tests/install.rs | 4 +- crates/package_manager/src/add.rs | 10 ++--- crates/package_manager/src/install.rs | 19 +++++---- .../src/install_without_lockfile.rs | 8 ++-- crates/package_manifest/src/lib.rs | 40 +++++++++---------- 12 files changed, 69 insertions(+), 75 deletions(-) diff --git a/crates/cli/src/cli_args.rs b/crates/cli/src/cli_args.rs index c1881ea34..b0898da03 100644 --- a/crates/cli/src/cli_args.rs +++ b/crates/cli/src/cli_args.rs @@ -53,34 +53,34 @@ impl CliArgs { /// Execute the command pub async fn run(self) -> miette::Result<()> { let CliArgs { command, dir } = self; - let package_json_path = || dir.join("package.json"); + let manifest_path = || dir.join("package.json"); let npmrc = || Npmrc::current(env::current_dir, home::home_dir, Default::default).leak(); - let state = || State::init(package_json_path(), npmrc()).wrap_err("initialize the state"); + let state = || State::init(manifest_path(), npmrc()).wrap_err("initialize the state"); match command { CliCommand::Init => { // init command throws an error if package.json file exist. - PackageManifest::init(&package_json_path()).wrap_err("initialize package.json")?; + PackageManifest::init(&manifest_path()).wrap_err("initialize package.json")?; } CliCommand::Add(args) => args.run(state()?).await?, CliCommand::Install(args) => args.run(state()?).await?, CliCommand::Test => { - let package_json = PackageManifest::from_path(package_json_path()) + let manifest = PackageManifest::from_path(manifest_path()) .wrap_err("getting the package.json in current directory")?; - if let Some(script) = package_json.script("test", false)? { + if let Some(script) = manifest.script("test", false)? { execute_shell(script) .wrap_err(format!("executing command: \"{0}\"", script))?; } } - CliCommand::Run(args) => args.run(package_json_path())?, + CliCommand::Run(args) => args.run(manifest_path())?, CliCommand::Start => { // Runs an arbitrary command specified in the package's start property of its scripts // object. If no start property is specified on the scripts object, it will attempt to // run node server.js as a default, failing if neither are present. // The intended usage of the property is to specify a command that starts your program. - let package_json = PackageManifest::from_path(package_json_path()) + let manifest = PackageManifest::from_path(manifest_path()) .wrap_err("getting the package.json in current directory")?; - let command = if let Some(script) = package_json.script("start", true)? { + let command = if let Some(script) = manifest.script("start", true)? { script } else { "node server.js" diff --git a/crates/cli/src/cli_args/add.rs b/crates/cli/src/cli_args/add.rs index 18f459232..1189ae264 100644 --- a/crates/cli/src/cli_args/add.rs +++ b/crates/cli/src/cli_args/add.rs @@ -85,13 +85,13 @@ impl AddArgs { pub async fn run(self, mut state: State) -> miette::Result<()> { // TODO: if a package already exists in another dependency group, don't remove the existing entry. - let State { tarball_cache, http_client, config, package_json, lockfile } = &mut state; + let State { tarball_cache, http_client, config, manifest, lockfile } = &mut state; Add { tarball_cache, http_client, config, - package_json, + manifest, lockfile: lockfile.as_ref(), list_dependency_groups: || self.dependency_options.dependency_groups(), package: &self.package, diff --git a/crates/cli/src/cli_args/install.rs b/crates/cli/src/cli_args/install.rs index c0d29e867..26c593de0 100644 --- a/crates/cli/src/cli_args/install.rs +++ b/crates/cli/src/cli_args/install.rs @@ -49,14 +49,14 @@ pub struct InstallArgs { impl InstallArgs { pub async fn run(self, state: State) -> miette::Result<()> { - let State { tarball_cache, http_client, config, package_json, lockfile } = &state; + let State { tarball_cache, http_client, config, manifest, lockfile } = &state; let InstallArgs { dependency_options, frozen_lockfile } = self; Install { tarball_cache, http_client, config, - package_json, + manifest, lockfile: lockfile.as_ref(), dependency_groups: dependency_options.dependency_groups(), frozen_lockfile, diff --git a/crates/cli/src/cli_args/run.rs b/crates/cli/src/cli_args/run.rs index aa07cb7df..0ab4cefa2 100644 --- a/crates/cli/src/cli_args/run.rs +++ b/crates/cli/src/cli_args/run.rs @@ -21,13 +21,13 @@ pub struct RunArgs { impl RunArgs { /// Execute the subcommand. - pub fn run(self, package_json_path: PathBuf) -> miette::Result<()> { + pub fn run(self, manifest_path: PathBuf) -> miette::Result<()> { let RunArgs { command, args, if_present } = self; - let package_json = PackageManifest::from_path(package_json_path) + let manifest = PackageManifest::from_path(manifest_path) .wrap_err("getting the package.json in current directory")?; - if let Some(script) = package_json.script(&command, if_present)? { + if let Some(script) = manifest.script(&command, if_present)? { let mut command = script.to_string(); // append an empty space between script and additional args command.push(' '); diff --git a/crates/cli/src/state.rs b/crates/cli/src/state.rs index a09a3d7a1..0b309105f 100644 --- a/crates/cli/src/state.rs +++ b/crates/cli/src/state.rs @@ -17,7 +17,7 @@ pub struct State { /// Configuration read from `.npmrc` pub config: &'static Npmrc, /// Data from the `package.json` file. - pub package_json: PackageManifest, + pub manifest: PackageManifest, /// Data from the `pnpm-lock.yaml` file. pub lockfile: Option, } @@ -35,13 +35,10 @@ pub enum InitStateError { impl State { /// Initialize the application state. - pub fn init( - package_json_path: PathBuf, - config: &'static Npmrc, - ) -> Result { + pub fn init(manifest_path: PathBuf, config: &'static Npmrc) -> Result { Ok(State { config, - package_json: package_json_path + manifest: manifest_path .pipe(PackageManifest::create_if_needed) .map_err(InitStateError::LoadPackageJson)?, lockfile: call_load_lockfile(config.lockfile, Lockfile::load_from_current_dir) diff --git a/crates/cli/tests/add.rs b/crates/cli/tests/add.rs index eb65560e8..22e7f28bf 100644 --- a/crates/cli/tests/add.rs +++ b/crates/cli/tests/add.rs @@ -13,10 +13,10 @@ fn should_install_all_dependencies() { eprintln!("Directory list"); insta::assert_debug_snapshot!(get_all_folders(dir.path())); - let package_json_path = dir.path().join("package.json"); + let manifest_path = dir.path().join("package.json"); - eprintln!("Ensure the manifest file ({package_json_path:?}) exists"); - assert!(package_json_path.exists()); + eprintln!("Ensure the manifest file ({manifest_path:?}) exists"); + assert!(manifest_path.exists()); let virtual_store_dir = dir.path().join("node_modules").join(".pacquet"); @@ -44,10 +44,10 @@ pub fn should_symlink_correctly() { eprintln!("Directory list"); insta::assert_debug_snapshot!(get_all_folders(dir.path())); - let package_json_path = dir.path().join("package.json"); + let manifest_path = dir.path().join("package.json"); - eprintln!("Ensure the manifest file ({package_json_path:?}) exists"); - assert!(package_json_path.exists()); + eprintln!("Ensure the manifest file ({manifest_path:?}) exists"); + assert!(manifest_path.exists()); let virtual_store_dir = dir.path().join("node_modules").join(".pacquet"); diff --git a/crates/cli/tests/init.rs b/crates/cli/tests/init.rs index 01bb9923b..c45e39a31 100644 --- a/crates/cli/tests/init.rs +++ b/crates/cli/tests/init.rs @@ -10,12 +10,12 @@ use std::{env, fs}; fn should_create_package_json() { let dir = exec_pacquet_in_temp_cwd(["init"]); - let package_json_path = dir.path().join("package.json"); - dbg!(&package_json_path); + let manifest_path = dir.path().join("package.json"); + dbg!(&manifest_path); eprintln!("Content of package.json"); let package_json_content = - fs::read_to_string(&package_json_path).expect("read from package.json"); + fs::read_to_string(&manifest_path).expect("read from package.json"); insta::assert_snapshot!(package_json_content); eprintln!("Created files"); @@ -26,11 +26,11 @@ fn should_create_package_json() { fn should_throw_on_existing_file() { let (command, dir) = pacquet_with_temp_cwd(); - let package_json_path = dir.path().join("package.json"); - dbg!(&package_json_path); + let manifest_path = dir.path().join("package.json"); + dbg!(&manifest_path); eprintln!("Creating package.json..."); - fs::write(&package_json_path, "{}").expect("write to package.json"); + fs::write(&manifest_path, "{}").expect("write to package.json"); eprintln!("Executing pacquet init..."); let output = command.with_arg("init").output().expect("execute pacquet init"); diff --git a/crates/cli/tests/install.rs b/crates/cli/tests/install.rs index 9edddd1e6..21bf5af1f 100644 --- a/crates/cli/tests/install.rs +++ b/crates/cli/tests/install.rs @@ -11,7 +11,7 @@ fn should_install_dependencies() { let (command, dir) = pacquet_with_temp_cwd(); eprintln!("Creating package.json..."); - let package_json_path = dir.path().join("package.json"); + let manifest_path = dir.path().join("package.json"); let package_json_content = serde_json::json!({ "dependencies": { "is-odd": "3.0.1", @@ -20,7 +20,7 @@ fn should_install_dependencies() { "fast-decode-uri-component": "1.0.1", }, }); - fs::write(&package_json_path, package_json_content.to_string()).expect("write to package.json"); + fs::write(&manifest_path, package_json_content.to_string()).expect("write to package.json"); eprintln!("Executing command..."); command.with_arg("install").assert().success(); diff --git a/crates/package_manager/src/add.rs b/crates/package_manager/src/add.rs index 0bcad3015..0351f6e03 100644 --- a/crates/package_manager/src/add.rs +++ b/crates/package_manager/src/add.rs @@ -23,7 +23,7 @@ where /// Configuration read from `.npmrc`. pub config: &'static Npmrc, /// Data from the `package.json` file. - pub package_json: &'a mut PackageManifest, + pub manifest: &'a mut PackageManifest, /// Data from the `pnpm-lock.yaml` file. pub lockfile: Option<&'a Lockfile>, /// Function that creates an iterator [`DependencyGroup`]s. @@ -54,7 +54,7 @@ where tarball_cache, http_client, config, - package_json, + manifest, lockfile, list_dependency_groups, package, @@ -72,7 +72,7 @@ where let version_range = latest_version.serialize(save_exact); for dependency_group in list_dependency_groups() { - package_json + manifest .add_dependency(package, &version_range, dependency_group) .map_err(AddError::AddDependencyToPackageJson)?; } @@ -81,7 +81,7 @@ where tarball_cache, http_client, config, - package_json, + manifest, lockfile, dependency_groups: list_dependency_groups(), frozen_lockfile: false, @@ -89,7 +89,7 @@ where .run() .await; - package_json.save().map_err(AddError::SavePackageJson)?; + manifest.save().map_err(AddError::SavePackageJson)?; Ok(()) } diff --git a/crates/package_manager/src/install.rs b/crates/package_manager/src/install.rs index dbcee3580..21aa3ee5e 100644 --- a/crates/package_manager/src/install.rs +++ b/crates/package_manager/src/install.rs @@ -18,7 +18,7 @@ where /// Configuration read from `.npmrc`. pub config: &'static Npmrc, /// Data from the `package.json` file. - pub package_json: &'a PackageManifest, + pub manifest: &'a PackageManifest, /// Data from the `pnpm-lock.yaml` file. pub lockfile: Option<&'a Lockfile>, /// List of [`DependencyGroup`]s. @@ -37,7 +37,7 @@ where tarball_cache, http_client, config, - package_json, + manifest, lockfile, dependency_groups, frozen_lockfile, @@ -51,7 +51,7 @@ where tarball_cache, http_client, config, - package_json, + manifest, dependency_groups, } .run() @@ -98,16 +98,15 @@ mod tests { let modules_dir = project_root.join("node_modules"); // TODO: we shouldn't have to define this let virtual_store_dir = modules_dir.join(".pacquet"); // TODO: we shouldn't have to define this - let package_json_path = dir.path().join("package.json"); - let mut package_json = - PackageManifest::create_if_needed(package_json_path.clone()).unwrap(); + let manifest_path = dir.path().join("package.json"); + let mut manifest = PackageManifest::create_if_needed(manifest_path.clone()).unwrap(); - package_json.add_dependency("is-odd", "3.0.1", DependencyGroup::Prod).unwrap(); - package_json + manifest.add_dependency("is-odd", "3.0.1", DependencyGroup::Prod).unwrap(); + manifest .add_dependency("fast-decode-uri-component", "1.0.1", DependencyGroup::Dev) .unwrap(); - package_json.save().unwrap(); + manifest.save().unwrap(); let mut config = Npmrc::new(); config.store_dir = store_dir.to_path_buf(); @@ -119,7 +118,7 @@ mod tests { tarball_cache: &Default::default(), http_client: &Default::default(), config, - package_json: &package_json, + manifest: &manifest, lockfile: None, dependency_groups: [ DependencyGroup::Prod, diff --git a/crates/package_manager/src/install_without_lockfile.rs b/crates/package_manager/src/install_without_lockfile.rs index ce1b59fe1..65e2f387a 100644 --- a/crates/package_manager/src/install_without_lockfile.rs +++ b/crates/package_manager/src/install_without_lockfile.rs @@ -27,7 +27,7 @@ pub struct InstallWithoutLockfile<'a, DependencyGroupList> { /// Configuration read from `.npmrc`. pub config: &'static Npmrc, /// Data from the `package.json` file. - pub package_json: &'a PackageManifest, + pub manifest: &'a PackageManifest, /// List of [`DependencyGroup`]s. pub dependency_groups: DependencyGroupList, } @@ -42,11 +42,11 @@ impl<'a, DependencyGroupList> InstallWithoutLockfile<'a, DependencyGroupList> { tarball_cache, http_client, config, - package_json, + manifest, dependency_groups, } = self; - let _: Vec<()> = package_json + let _: Vec<()> = manifest .dependencies(dependency_groups.into_iter()) .map(|(name, version_range)| async move { let dependency = InstallPackageFromRegistry { @@ -65,7 +65,7 @@ impl<'a, DependencyGroupList> InstallWithoutLockfile<'a, DependencyGroupList> { tarball_cache, http_client, config, - package_json, + manifest, dependency_groups: (), } .install_dependencies_from_registry(&dependency) diff --git a/crates/package_manifest/src/lib.rs b/crates/package_manifest/src/lib.rs index 1269e8185..89edbbbcb 100644 --- a/crates/package_manifest/src/lib.rs +++ b/crates/package_manifest/src/lib.rs @@ -89,10 +89,10 @@ impl PackageManifest { .and_then(|folder| folder.file_name()) .and_then(|file_name| file_name.to_str()) .unwrap_or(""); - let package_json = PackageManifest::create_init_package_json(name); - let contents = serde_json::to_string_pretty(&package_json)?; + let manifest = PackageManifest::create_init_package_json(name); + let contents = serde_json::to_string_pretty(&manifest)?; fs::write(path, &contents)?; // TODO: forbid overwriting existing files - Ok((package_json, contents)) + Ok((manifest, contents)) } fn read_from_file(path: &Path) -> Result { @@ -225,8 +225,8 @@ mod tests { #[test] fn test_init_package_json_content() { - let package_json = PackageManifest::create_init_package_json("test"); - assert_snapshot!(serde_json::to_string_pretty(&package_json).unwrap()); + let manifest = PackageManifest::create_init_package_json("test"); + assert_snapshot!(serde_json::to_string_pretty(&manifest).unwrap()); } #[test] @@ -250,14 +250,13 @@ mod tests { fn should_add_dependency() { let dir = tempdir().unwrap(); let tmp = dir.path().join("package.json"); - let mut package_json = PackageManifest::create_if_needed(tmp.clone()).unwrap(); - package_json.add_dependency("fastify", "1.0.0", DependencyGroup::Prod).unwrap(); + let mut manifest = PackageManifest::create_if_needed(tmp.clone()).unwrap(); + manifest.add_dependency("fastify", "1.0.0", DependencyGroup::Prod).unwrap(); - let dependencies: HashMap<_, _> = - package_json.dependencies([DependencyGroup::Prod]).collect(); + let dependencies: HashMap<_, _> = manifest.dependencies([DependencyGroup::Prod]).collect(); assert!(dependencies.contains_key("fastify")); assert_eq!(dependencies.get("fastify").unwrap(), &"1.0.0"); - package_json.save().unwrap(); + manifest.save().unwrap(); assert!(read_to_string(tmp).unwrap().contains("fastify")); } @@ -265,8 +264,8 @@ mod tests { fn should_throw_on_missing_command() { let dir = tempdir().unwrap(); let tmp = dir.path().join("package.json"); - let package_json = PackageManifest::create_if_needed(tmp).unwrap(); - package_json.script("dev", false).expect_err("dev command should not exist"); + let manifest = PackageManifest::create_if_needed(tmp).unwrap(); + manifest.script("dev", false).expect_err("dev command should not exist"); } #[test] @@ -280,10 +279,10 @@ mod tests { "#; let tmp = NamedTempFile::new().unwrap(); write!(tmp.as_file(), "{}", data).unwrap(); - let package_json = PackageManifest::create_if_needed(tmp.path().to_path_buf()).unwrap(); - package_json.script("test", false).unwrap(); - package_json.script("invalid", false).expect_err("invalid command should not exist"); - package_json.script("invalid", true).unwrap(); + let manifest = PackageManifest::create_if_needed(tmp.path().to_path_buf()).unwrap(); + manifest.script("test", false).unwrap(); + manifest.script("invalid", false).expect_err("invalid command should not exist"); + manifest.script("invalid", true).unwrap(); } #[test] @@ -300,8 +299,8 @@ mod tests { "#; let tmp = NamedTempFile::new().unwrap(); write!(tmp.as_file(), "{}", data).unwrap(); - let package_json = PackageManifest::create_if_needed(tmp.path().to_path_buf()).unwrap(); - let dependencies = |groups| package_json.dependencies(groups).collect::>(); + let manifest = PackageManifest::create_if_needed(tmp.path().to_path_buf()).unwrap(); + let dependencies = |groups| manifest.dependencies(groups).collect::>(); assert!(dependencies([DependencyGroup::Peer]).contains_key("fast-querystring")); assert!(dependencies([DependencyGroup::Prod]).contains_key("fastify")); } @@ -322,9 +321,8 @@ mod tests { eprintln!("CASE: {data}"); let tmp = NamedTempFile::new().unwrap(); write!(tmp.as_file(), "{}", data).unwrap(); - let package_json = - PackageManifest::create_if_needed(tmp.path().to_path_buf()).unwrap(); - let bundle = package_json.bundle_dependencies().unwrap(); + let manifest = PackageManifest::create_if_needed(tmp.path().to_path_buf()).unwrap(); + let bundle = manifest.bundle_dependencies().unwrap(); assert_eq!(bundle, $output); }}; } From 601a90f7675c4cf28fafbe8fc78554e782d1852c Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 16 Oct 2023 14:19:52 +0700 Subject: [PATCH 198/210] style: cargo fmt --- crates/cli/tests/init.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/cli/tests/init.rs b/crates/cli/tests/init.rs index c45e39a31..56d12b28c 100644 --- a/crates/cli/tests/init.rs +++ b/crates/cli/tests/init.rs @@ -14,8 +14,7 @@ fn should_create_package_json() { dbg!(&manifest_path); eprintln!("Content of package.json"); - let package_json_content = - fs::read_to_string(&manifest_path).expect("read from package.json"); + let package_json_content = fs::read_to_string(&manifest_path).expect("read from package.json"); insta::assert_snapshot!(package_json_content); eprintln!("Created files"); From a38bb0b73578e03a77b27b73c29506a20a806e66 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 16 Oct 2023 14:25:07 +0700 Subject: [PATCH 199/210] refactor: rename more --- crates/cli/src/state.rs | 6 +++--- crates/package_manager/src/add.rs | 10 +++++----- crates/package_manifest/src/lib.rs | 28 ++++++++++++++-------------- crates/registry/src/package.rs | 2 +- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/crates/cli/src/state.rs b/crates/cli/src/state.rs index 0b309105f..6ed86c7d5 100644 --- a/crates/cli/src/state.rs +++ b/crates/cli/src/state.rs @@ -2,7 +2,7 @@ use derive_more::{Display, Error}; use miette::Diagnostic; use pacquet_lockfile::{LoadLockfileError, Lockfile}; use pacquet_npmrc::Npmrc; -use pacquet_package_manifest::{PackageJsonError, PackageManifest}; +use pacquet_package_manifest::{PackageManifest, PackageManifestError}; use pacquet_tarball::Cache; use pipe_trait::Pipe; use reqwest::Client; @@ -27,7 +27,7 @@ pub struct State { #[non_exhaustive] pub enum InitStateError { #[diagnostic(transparent)] - LoadPackageJson(#[error(source)] PackageJsonError), + LoadManifest(#[error(source)] PackageManifestError), #[diagnostic(transparent)] LoadLockfile(#[error(source)] LoadLockfileError), @@ -40,7 +40,7 @@ impl State { config, manifest: manifest_path .pipe(PackageManifest::create_if_needed) - .map_err(InitStateError::LoadPackageJson)?, + .map_err(InitStateError::LoadManifest)?, lockfile: call_load_lockfile(config.lockfile, Lockfile::load_from_current_dir) .map_err(InitStateError::LoadLockfile)?, http_client: Client::new(), diff --git a/crates/package_manager/src/add.rs b/crates/package_manager/src/add.rs index 0351f6e03..8705a7589 100644 --- a/crates/package_manager/src/add.rs +++ b/crates/package_manager/src/add.rs @@ -3,7 +3,7 @@ use derive_more::{Display, Error}; use miette::Diagnostic; use pacquet_lockfile::Lockfile; use pacquet_npmrc::Npmrc; -use pacquet_package_manifest::PackageJsonError; +use pacquet_package_manifest::PackageManifestError; use pacquet_package_manifest::{DependencyGroup, PackageManifest}; use pacquet_registry::{PackageTag, PackageVersion}; use pacquet_tarball::Cache; @@ -38,9 +38,9 @@ where #[derive(Debug, Display, Error, Diagnostic)] pub enum AddError { #[display("Failed to add package to manifest: {_0}")] - AddDependencyToPackageJson(#[error(source)] PackageJsonError), + AddDependencyToManifest(#[error(source)] PackageManifestError), #[display("Failed save the manifest file: {_0}")] - SavePackageJson(#[error(source)] PackageJsonError), + SaveManifest(#[error(source)] PackageManifestError), } impl<'a, ListDependencyGroups, DependencyGroupList> @@ -74,7 +74,7 @@ where for dependency_group in list_dependency_groups() { manifest .add_dependency(package, &version_range, dependency_group) - .map_err(AddError::AddDependencyToPackageJson)?; + .map_err(AddError::AddDependencyToManifest)?; } Install { @@ -89,7 +89,7 @@ where .run() .await; - manifest.save().map_err(AddError::SavePackageJson)?; + manifest.save().map_err(AddError::SaveManifest)?; Ok(()) } diff --git a/crates/package_manifest/src/lib.rs b/crates/package_manifest/src/lib.rs index 89edbbbcb..2f6112bc2 100644 --- a/crates/package_manifest/src/lib.rs +++ b/crates/package_manifest/src/lib.rs @@ -12,7 +12,7 @@ use strum::IntoStaticStr; #[derive(Debug, Display, Error, From, Diagnostic)] #[non_exhaustive] -pub enum PackageJsonError { +pub enum PackageManifestError { #[diagnostic(code(pacquet_package_manifest::serialization_error))] Serialization(serde_json::Error), // TODO: remove derive(From), split this variant @@ -83,7 +83,7 @@ impl PackageManifest { }) } - fn write_to_file(path: &Path) -> Result<(Value, String), PackageJsonError> { + fn write_to_file(path: &Path) -> Result<(Value, String), PackageManifestError> { let name = path .parent() .and_then(|folder| folder.file_name()) @@ -95,30 +95,30 @@ impl PackageManifest { Ok((manifest, contents)) } - fn read_from_file(path: &Path) -> Result { + fn read_from_file(path: &Path) -> Result { let contents = fs::read_to_string(path)?; - serde_json::from_str(&contents).map_err(PackageJsonError::from) + serde_json::from_str(&contents).map_err(PackageManifestError::from) } - pub fn init(path: &Path) -> Result<(), PackageJsonError> { + pub fn init(path: &Path) -> Result<(), PackageManifestError> { if path.exists() { - return Err(PackageJsonError::AlreadyExist); + return Err(PackageManifestError::AlreadyExist); } let (_, contents) = PackageManifest::write_to_file(path)?; println!("Wrote to {path}\n\n{contents}", path = path.display()); Ok(()) } - pub fn from_path(path: PathBuf) -> Result { + pub fn from_path(path: PathBuf) -> Result { if !path.exists() { - return Err(PackageJsonError::NoImporterManifestFound(path.display().to_string())); + return Err(PackageManifestError::NoImporterManifestFound(path.display().to_string())); } let value = PackageManifest::read_from_file(&path)?; Ok(PackageManifest { path, value }) } - pub fn create_if_needed(path: PathBuf) -> Result { + pub fn create_if_needed(path: PathBuf) -> Result { let value = if path.exists() { PackageManifest::read_from_file(&path)? } else { @@ -136,7 +136,7 @@ impl PackageManifest { &self.value } - pub fn save(&self) -> Result<(), PackageJsonError> { + pub fn save(&self) -> Result<(), PackageManifestError> { let mut file = fs::File::create(&self.path)?; let contents = serde_json::to_string_pretty(&self.value)?; file.write_all(contents.as_bytes())?; @@ -171,13 +171,13 @@ impl PackageManifest { name: &str, version: &str, dependency_group: DependencyGroup, - ) -> Result<(), PackageJsonError> { + ) -> Result<(), PackageManifestError> { let dependency_type: &str = dependency_group.into(); if let Some(field) = self.value.get_mut(dependency_type) { if let Some(dependencies) = field.as_object_mut() { dependencies.insert(name.to_string(), Value::String(version.to_string())); } else { - return Err(PackageJsonError::InvalidAttribute( + return Err(PackageManifestError::InvalidAttribute( "dependencies attribute should be an object".to_string(), )); } @@ -193,7 +193,7 @@ impl PackageManifest { &self, command: &str, if_present: bool, - ) -> Result, PackageJsonError> { + ) -> Result, PackageManifestError> { if let Some(script_str) = self .value .get("scripts") @@ -206,7 +206,7 @@ impl PackageManifest { if if_present { Ok(None) } else { - Err(PackageJsonError::NoScript(command.to_string())) + Err(PackageManifestError::NoScript(command.to_string())) } } } diff --git a/crates/registry/src/package.rs b/crates/registry/src/package.rs index 79f0f03ad..8779f1c8a 100644 --- a/crates/registry/src/package.rs +++ b/crates/registry/src/package.rs @@ -46,7 +46,7 @@ impl Package { } pub fn pinned_version(&self, version_range: &str) -> Option<&PackageVersion> { - let range: node_semver::Range = version_range.parse().unwrap(); // TODO: this step should have happened in PackageJson + let range: node_semver::Range = version_range.parse().unwrap(); // TODO: this step should have happened in PackageManifest let mut satisfied_versions = self .versions .values() From 3fc19383a060c16d3121b8c7aacd6980e3bb4d87 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 16 Oct 2023 14:28:33 +0700 Subject: [PATCH 200/210] style: consistent crate dir name --- Cargo.toml | 4 ++-- crates/{package_manager => package-manager}/Cargo.toml | 0 crates/{package_manager => package-manager}/src/add.rs | 0 .../src/create_cas_files.rs | 0 .../src/create_symlink_layout.rs | 0 .../src/create_virtual_dir_by_snapshot.rs | 0 .../src/create_virtual_store.rs | 0 crates/{package_manager => package-manager}/src/install.rs | 0 .../src/install_frozen_lockfile.rs | 0 .../src/install_package_by_snapshot.rs | 0 .../src/install_package_from_registry.rs | 0 .../src/install_without_lockfile.rs | 0 crates/{package_manager => package-manager}/src/lib.rs | 0 crates/{package_manager => package-manager}/src/link_file.rs | 0 ..._manager__install__tests__should_install_dependencies.snap | 0 .../src/symlink_direct_dependencies.rs | 0 .../src/symlink_package.rs | 0 crates/{package_manifest => package-manifest}/Cargo.toml | 0 crates/{package_manifest => package-manifest}/src/lib.rs | 0 ...et_package_manifest__tests__init_package_json_content.snap | 0 20 files changed, 2 insertions(+), 2 deletions(-) rename crates/{package_manager => package-manager}/Cargo.toml (100%) rename crates/{package_manager => package-manager}/src/add.rs (100%) rename crates/{package_manager => package-manager}/src/create_cas_files.rs (100%) rename crates/{package_manager => package-manager}/src/create_symlink_layout.rs (100%) rename crates/{package_manager => package-manager}/src/create_virtual_dir_by_snapshot.rs (100%) rename crates/{package_manager => package-manager}/src/create_virtual_store.rs (100%) rename crates/{package_manager => package-manager}/src/install.rs (100%) rename crates/{package_manager => package-manager}/src/install_frozen_lockfile.rs (100%) rename crates/{package_manager => package-manager}/src/install_package_by_snapshot.rs (100%) rename crates/{package_manager => package-manager}/src/install_package_from_registry.rs (100%) rename crates/{package_manager => package-manager}/src/install_without_lockfile.rs (100%) rename crates/{package_manager => package-manager}/src/lib.rs (100%) rename crates/{package_manager => package-manager}/src/link_file.rs (100%) rename crates/{package_manager => package-manager}/src/snapshots/pacquet_package_manager__install__tests__should_install_dependencies.snap (100%) rename crates/{package_manager => package-manager}/src/symlink_direct_dependencies.rs (100%) rename crates/{package_manager => package-manager}/src/symlink_package.rs (100%) rename crates/{package_manifest => package-manifest}/Cargo.toml (100%) rename crates/{package_manifest => package-manifest}/src/lib.rs (100%) rename crates/{package_manifest => package-manifest}/src/snapshots/pacquet_package_manifest__tests__init_package_json_content.snap (100%) diff --git a/Cargo.toml b/Cargo.toml index 411dfcee6..adb7aacb3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,8 +18,8 @@ pacquet_fs = { path = "crates/fs" } pacquet_registry = { path = "crates/registry" } pacquet_tarball = { path = "crates/tarball" } pacquet_testing_utils = { path = "crates/testing-utils" } -pacquet_package_manifest = { path = "crates/package_manifest" } -pacquet_package_manager = { path = "crates/package_manager" } +pacquet_package_manifest = { path = "crates/package-manifest" } +pacquet_package_manager = { path = "crates/package-manager" } pacquet_lockfile = { path = "crates/lockfile" } pacquet_npmrc = { path = "crates/npmrc" } pacquet_executor = { path = "crates/executor" } diff --git a/crates/package_manager/Cargo.toml b/crates/package-manager/Cargo.toml similarity index 100% rename from crates/package_manager/Cargo.toml rename to crates/package-manager/Cargo.toml diff --git a/crates/package_manager/src/add.rs b/crates/package-manager/src/add.rs similarity index 100% rename from crates/package_manager/src/add.rs rename to crates/package-manager/src/add.rs diff --git a/crates/package_manager/src/create_cas_files.rs b/crates/package-manager/src/create_cas_files.rs similarity index 100% rename from crates/package_manager/src/create_cas_files.rs rename to crates/package-manager/src/create_cas_files.rs diff --git a/crates/package_manager/src/create_symlink_layout.rs b/crates/package-manager/src/create_symlink_layout.rs similarity index 100% rename from crates/package_manager/src/create_symlink_layout.rs rename to crates/package-manager/src/create_symlink_layout.rs diff --git a/crates/package_manager/src/create_virtual_dir_by_snapshot.rs b/crates/package-manager/src/create_virtual_dir_by_snapshot.rs similarity index 100% rename from crates/package_manager/src/create_virtual_dir_by_snapshot.rs rename to crates/package-manager/src/create_virtual_dir_by_snapshot.rs diff --git a/crates/package_manager/src/create_virtual_store.rs b/crates/package-manager/src/create_virtual_store.rs similarity index 100% rename from crates/package_manager/src/create_virtual_store.rs rename to crates/package-manager/src/create_virtual_store.rs diff --git a/crates/package_manager/src/install.rs b/crates/package-manager/src/install.rs similarity index 100% rename from crates/package_manager/src/install.rs rename to crates/package-manager/src/install.rs diff --git a/crates/package_manager/src/install_frozen_lockfile.rs b/crates/package-manager/src/install_frozen_lockfile.rs similarity index 100% rename from crates/package_manager/src/install_frozen_lockfile.rs rename to crates/package-manager/src/install_frozen_lockfile.rs diff --git a/crates/package_manager/src/install_package_by_snapshot.rs b/crates/package-manager/src/install_package_by_snapshot.rs similarity index 100% rename from crates/package_manager/src/install_package_by_snapshot.rs rename to crates/package-manager/src/install_package_by_snapshot.rs diff --git a/crates/package_manager/src/install_package_from_registry.rs b/crates/package-manager/src/install_package_from_registry.rs similarity index 100% rename from crates/package_manager/src/install_package_from_registry.rs rename to crates/package-manager/src/install_package_from_registry.rs diff --git a/crates/package_manager/src/install_without_lockfile.rs b/crates/package-manager/src/install_without_lockfile.rs similarity index 100% rename from crates/package_manager/src/install_without_lockfile.rs rename to crates/package-manager/src/install_without_lockfile.rs diff --git a/crates/package_manager/src/lib.rs b/crates/package-manager/src/lib.rs similarity index 100% rename from crates/package_manager/src/lib.rs rename to crates/package-manager/src/lib.rs diff --git a/crates/package_manager/src/link_file.rs b/crates/package-manager/src/link_file.rs similarity index 100% rename from crates/package_manager/src/link_file.rs rename to crates/package-manager/src/link_file.rs diff --git a/crates/package_manager/src/snapshots/pacquet_package_manager__install__tests__should_install_dependencies.snap b/crates/package-manager/src/snapshots/pacquet_package_manager__install__tests__should_install_dependencies.snap similarity index 100% rename from crates/package_manager/src/snapshots/pacquet_package_manager__install__tests__should_install_dependencies.snap rename to crates/package-manager/src/snapshots/pacquet_package_manager__install__tests__should_install_dependencies.snap diff --git a/crates/package_manager/src/symlink_direct_dependencies.rs b/crates/package-manager/src/symlink_direct_dependencies.rs similarity index 100% rename from crates/package_manager/src/symlink_direct_dependencies.rs rename to crates/package-manager/src/symlink_direct_dependencies.rs diff --git a/crates/package_manager/src/symlink_package.rs b/crates/package-manager/src/symlink_package.rs similarity index 100% rename from crates/package_manager/src/symlink_package.rs rename to crates/package-manager/src/symlink_package.rs diff --git a/crates/package_manifest/Cargo.toml b/crates/package-manifest/Cargo.toml similarity index 100% rename from crates/package_manifest/Cargo.toml rename to crates/package-manifest/Cargo.toml diff --git a/crates/package_manifest/src/lib.rs b/crates/package-manifest/src/lib.rs similarity index 100% rename from crates/package_manifest/src/lib.rs rename to crates/package-manifest/src/lib.rs diff --git a/crates/package_manifest/src/snapshots/pacquet_package_manifest__tests__init_package_json_content.snap b/crates/package-manifest/src/snapshots/pacquet_package_manifest__tests__init_package_json_content.snap similarity index 100% rename from crates/package_manifest/src/snapshots/pacquet_package_manifest__tests__init_package_json_content.snap rename to crates/package-manifest/src/snapshots/pacquet_package_manifest__tests__init_package_json_content.snap From 075e788f166ed73d3cc79be6fefcdf1e6dc4697e Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 16 Oct 2023 15:06:13 +0700 Subject: [PATCH 201/210] refactor: use kebab-case where possible it is easier to type --- Cargo.lock | 78 +++++++++++++-------------- Cargo.toml | 24 ++++----- crates/cafs/Cargo.toml | 2 +- crates/cli/Cargo.toml | 24 ++++----- crates/diagnostics/Cargo.toml | 2 +- crates/executor/Cargo.toml | 2 +- crates/fs/Cargo.toml | 2 +- crates/lockfile/Cargo.toml | 6 +-- crates/npmrc/Cargo.toml | 2 +- crates/package-manager/Cargo.toml | 16 +++--- crates/package-manifest/Cargo.toml | 2 +- crates/registry/Cargo.toml | 4 +- crates/tarball/Cargo.toml | 6 +-- crates/testing-utils/Cargo.toml | 2 +- tasks/integrated-benchmark/Cargo.toml | 2 +- tasks/micro-benchmark/Cargo.toml | 6 +-- 16 files changed, 90 insertions(+), 90 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1c6967661..3eb1fe9a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1298,7 +1298,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] -name = "pacquet_cafs" +name = "pacquet-cafs" version = "0.0.1" dependencies = [ "derive_more", @@ -1309,7 +1309,7 @@ dependencies = [ ] [[package]] -name = "pacquet_cli" +name = "pacquet-cli" version = "0.0.1" dependencies = [ "assert_cmd", @@ -1320,17 +1320,17 @@ dependencies = [ "home", "insta", "miette", - "pacquet_cafs", - "pacquet_diagnostics", - "pacquet_executor", - "pacquet_fs", - "pacquet_lockfile", - "pacquet_npmrc", - "pacquet_package_manager", - "pacquet_package_manifest", - "pacquet_registry", - "pacquet_tarball", - "pacquet_testing_utils", + "pacquet-cafs", + "pacquet-diagnostics", + "pacquet-executor", + "pacquet-fs", + "pacquet-lockfile", + "pacquet-npmrc", + "pacquet-package-manager", + "pacquet-package-manifest", + "pacquet-registry", + "pacquet-tarball", + "pacquet-testing-utils", "pipe-trait", "pretty_assertions", "reqwest", @@ -1340,7 +1340,7 @@ dependencies = [ ] [[package]] -name = "pacquet_diagnostics" +name = "pacquet-diagnostics" version = "0.0.1" dependencies = [ "miette", @@ -1349,7 +1349,7 @@ dependencies = [ ] [[package]] -name = "pacquet_executor" +name = "pacquet-executor" version = "0.0.1" dependencies = [ "derive_more", @@ -1357,14 +1357,14 @@ dependencies = [ ] [[package]] -name = "pacquet_fs" +name = "pacquet-fs" version = "0.0.1" dependencies = [ "junction", ] [[package]] -name = "pacquet_integrated_benchmark" +name = "pacquet-integrated-benchmark" version = "0.0.0" dependencies = [ "clap", @@ -1377,13 +1377,13 @@ dependencies = [ ] [[package]] -name = "pacquet_lockfile" +name = "pacquet-lockfile" version = "0.0.1" dependencies = [ "derive_more", "node-semver", - "pacquet_diagnostics", - "pacquet_package_manifest", + "pacquet-diagnostics", + "pacquet-package-manifest", "pipe-trait", "pretty_assertions", "serde", @@ -1393,15 +1393,15 @@ dependencies = [ ] [[package]] -name = "pacquet_micro_benchmark" +name = "pacquet-micro-benchmark" version = "0.0.0" dependencies = [ "clap", "criterion", "mockito", "node-semver", - "pacquet_registry", - "pacquet_tarball", + "pacquet-registry", + "pacquet-tarball", "pipe-trait", "project-root", "reqwest", @@ -1410,7 +1410,7 @@ dependencies = [ ] [[package]] -name = "pacquet_npmrc" +name = "pacquet-npmrc" version = "0.0.1" dependencies = [ "home", @@ -1422,7 +1422,7 @@ dependencies = [ ] [[package]] -name = "pacquet_package_manager" +name = "pacquet-package-manager" version = "0.0.1" dependencies = [ "async-recursion", @@ -1431,13 +1431,13 @@ dependencies = [ "insta", "miette", "node-semver", - "pacquet_fs", - "pacquet_lockfile", - "pacquet_npmrc", - "pacquet_package_manifest", - "pacquet_registry", - "pacquet_tarball", - "pacquet_testing_utils", + "pacquet-fs", + "pacquet-lockfile", + "pacquet-npmrc", + "pacquet-package-manifest", + "pacquet-registry", + "pacquet-tarball", + "pacquet-testing-utils", "pipe-trait", "pretty_assertions", "rayon", @@ -1450,7 +1450,7 @@ dependencies = [ ] [[package]] -name = "pacquet_package_manifest" +name = "pacquet-package-manifest" version = "0.0.1" dependencies = [ "derive_more", @@ -1465,13 +1465,13 @@ dependencies = [ ] [[package]] -name = "pacquet_registry" +name = "pacquet-registry" version = "0.0.1" dependencies = [ "derive_more", "miette", "node-semver", - "pacquet_diagnostics", + "pacquet-diagnostics", "pipe-trait", "pretty_assertions", "reqwest", @@ -1482,14 +1482,14 @@ dependencies = [ ] [[package]] -name = "pacquet_tarball" +name = "pacquet-tarball" version = "0.0.1" dependencies = [ "dashmap", "derive_more", "miette", - "pacquet_cafs", - "pacquet_diagnostics", + "pacquet-cafs", + "pacquet-diagnostics", "pipe-trait", "pretty_assertions", "reqwest", @@ -1502,7 +1502,7 @@ dependencies = [ ] [[package]] -name = "pacquet_testing_utils" +name = "pacquet-testing-utils" version = "0.0.0" dependencies = [ "assert_cmd", diff --git a/Cargo.toml b/Cargo.toml index adb7aacb3..92d2ea579 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,18 +13,18 @@ repository = "https://github.com/anonrig/pacquet" [workspace.dependencies] # Crates -pacquet_cli = { path = "crates/cli" } -pacquet_fs = { path = "crates/fs" } -pacquet_registry = { path = "crates/registry" } -pacquet_tarball = { path = "crates/tarball" } -pacquet_testing_utils = { path = "crates/testing-utils" } -pacquet_package_manifest = { path = "crates/package-manifest" } -pacquet_package_manager = { path = "crates/package-manager" } -pacquet_lockfile = { path = "crates/lockfile" } -pacquet_npmrc = { path = "crates/npmrc" } -pacquet_executor = { path = "crates/executor" } -pacquet_cafs = { path = "crates/cafs" } -pacquet_diagnostics = { path = "crates/diagnostics" } +pacquet-cli = { path = "crates/cli" } +pacquet-fs = { path = "crates/fs" } +pacquet-registry = { path = "crates/registry" } +pacquet-tarball = { path = "crates/tarball" } +pacquet-testing-utils = { path = "crates/testing-utils" } +pacquet-package-manifest = { path = "crates/package-manifest" } +pacquet-package-manager = { path = "crates/package-manager" } +pacquet-lockfile = { path = "crates/lockfile" } +pacquet-npmrc = { path = "crates/npmrc" } +pacquet-executor = { path = "crates/executor" } +pacquet-cafs = { path = "crates/cafs" } +pacquet-diagnostics = { path = "crates/diagnostics" } # Dependencies async-recursion = { version = "1.0.5" } diff --git a/crates/cafs/Cargo.toml b/crates/cafs/Cargo.toml index bc13baa2f..02e0b9f5e 100644 --- a/crates/cafs/Cargo.toml +++ b/crates/cafs/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pacquet_cafs" +name = "pacquet-cafs" version = "0.0.1" publish = false authors.workspace = true diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 4b892f6b0..d8932cd1b 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pacquet_cli" +name = "pacquet-cli" version = "0.0.1" publish = false authors.workspace = true @@ -15,16 +15,16 @@ name = "pacquet" path = "src/bin/main.rs" [dependencies] -pacquet_cafs = { workspace = true } -pacquet_executor = { workspace = true } -pacquet_fs = { workspace = true } -pacquet_lockfile = { workspace = true } -pacquet_npmrc = { workspace = true } -pacquet_package_manifest = { workspace = true } -pacquet_package_manager = { workspace = true } -pacquet_registry = { workspace = true } -pacquet_tarball = { workspace = true } -pacquet_diagnostics = { workspace = true } +pacquet-cafs = { workspace = true } +pacquet-executor = { workspace = true } +pacquet-fs = { workspace = true } +pacquet-lockfile = { workspace = true } +pacquet-npmrc = { workspace = true } +pacquet-package-manifest = { workspace = true } +pacquet-package-manager = { workspace = true } +pacquet-registry = { workspace = true } +pacquet-tarball = { workspace = true } +pacquet-diagnostics = { workspace = true } clap = { workspace = true } derive_more = { workspace = true } @@ -35,7 +35,7 @@ pipe-trait = { workspace = true } tokio = { workspace = true } [dev-dependencies] -pacquet_testing_utils = { workspace = true } +pacquet-testing-utils = { workspace = true } assert_cmd = { workspace = true } dunce = { workspace = true } diff --git a/crates/diagnostics/Cargo.toml b/crates/diagnostics/Cargo.toml index a9e667a98..35c7c9876 100644 --- a/crates/diagnostics/Cargo.toml +++ b/crates/diagnostics/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pacquet_diagnostics" +name = "pacquet-diagnostics" version = "0.0.1" publish = false authors.workspace = true diff --git a/crates/executor/Cargo.toml b/crates/executor/Cargo.toml index c7f82c464..c457268b0 100644 --- a/crates/executor/Cargo.toml +++ b/crates/executor/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pacquet_executor" +name = "pacquet-executor" version = "0.0.1" publish = false authors.workspace = true diff --git a/crates/fs/Cargo.toml b/crates/fs/Cargo.toml index eba300d13..71b7095df 100644 --- a/crates/fs/Cargo.toml +++ b/crates/fs/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pacquet_fs" +name = "pacquet-fs" description = "Filesystem utility functions used by pacquet" version = "0.0.1" publish = false diff --git a/crates/lockfile/Cargo.toml b/crates/lockfile/Cargo.toml index b1e44fe59..25bc77151 100644 --- a/crates/lockfile/Cargo.toml +++ b/crates/lockfile/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pacquet_lockfile" +name = "pacquet-lockfile" version = "0.0.1" publish = false authors.workspace = true @@ -11,8 +11,8 @@ license.workspace = true repository.workspace = true [dependencies] -pacquet_diagnostics = { workspace = true } -pacquet_package_manifest = { workspace = true } +pacquet-diagnostics = { workspace = true } +pacquet-package-manifest = { workspace = true } derive_more = { workspace = true } node-semver = { workspace = true } diff --git a/crates/npmrc/Cargo.toml b/crates/npmrc/Cargo.toml index 9ea53c7fa..ec11d9ab4 100644 --- a/crates/npmrc/Cargo.toml +++ b/crates/npmrc/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pacquet_npmrc" +name = "pacquet-npmrc" version = "0.0.1" publish = false authors.workspace = true diff --git a/crates/package-manager/Cargo.toml b/crates/package-manager/Cargo.toml index 60b463acd..455092e60 100644 --- a/crates/package-manager/Cargo.toml +++ b/crates/package-manager/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pacquet_package_manager" +name = "pacquet-package-manager" version = "0.0.1" publish = false authors.workspace = true @@ -11,12 +11,12 @@ license.workspace = true repository.workspace = true [dependencies] -pacquet_fs = { workspace = true } -pacquet_lockfile = { workspace = true } -pacquet_npmrc = { workspace = true } -pacquet_package_manifest = { workspace = true } -pacquet_registry = { workspace = true } -pacquet_tarball = { workspace = true } +pacquet-fs = { workspace = true } +pacquet-lockfile = { workspace = true } +pacquet-npmrc = { workspace = true } +pacquet-package-manifest = { workspace = true } +pacquet-registry = { workspace = true } +pacquet-tarball = { workspace = true } async-recursion = { workspace = true } derive_more = { workspace = true } @@ -30,7 +30,7 @@ tracing = { workspace = true } miette = { workspace = true } [dev-dependencies] -pacquet_testing_utils = { workspace = true } +pacquet-testing-utils = { workspace = true } node-semver = { workspace = true } insta = { workspace = true } diff --git a/crates/package-manifest/Cargo.toml b/crates/package-manifest/Cargo.toml index d73e4eec3..3716911df 100644 --- a/crates/package-manifest/Cargo.toml +++ b/crates/package-manifest/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pacquet_package_manifest" +name = "pacquet-package-manifest" version = "0.0.1" publish = false authors.workspace = true diff --git a/crates/registry/Cargo.toml b/crates/registry/Cargo.toml index 9a814d190..c230413d8 100644 --- a/crates/registry/Cargo.toml +++ b/crates/registry/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pacquet_registry" +name = "pacquet-registry" version = "0.0.1" publish = false authors.workspace = true @@ -11,7 +11,7 @@ license.workspace = true repository.workspace = true [dependencies] -pacquet_diagnostics = { workspace = true } +pacquet-diagnostics = { workspace = true } derive_more = { workspace = true } reqwest = { workspace = true } diff --git a/crates/tarball/Cargo.toml b/crates/tarball/Cargo.toml index 4404494bf..ae787be44 100644 --- a/crates/tarball/Cargo.toml +++ b/crates/tarball/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pacquet_tarball" +name = "pacquet-tarball" version = "0.0.1" publish = false authors.workspace = true @@ -11,8 +11,8 @@ license.workspace = true repository.workspace = true [dependencies] -pacquet_cafs = { workspace = true } -pacquet_diagnostics = { workspace = true } +pacquet-cafs = { workspace = true } +pacquet-diagnostics = { workspace = true } dashmap = { workspace = true } derive_more = { workspace = true } diff --git a/crates/testing-utils/Cargo.toml b/crates/testing-utils/Cargo.toml index b67d0e73a..c645c9045 100644 --- a/crates/testing-utils/Cargo.toml +++ b/crates/testing-utils/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pacquet_testing_utils" +name = "pacquet-testing-utils" version = "0.0.0" description = "Common utilities to test pacquet code" publish = false diff --git a/tasks/integrated-benchmark/Cargo.toml b/tasks/integrated-benchmark/Cargo.toml index 5e9c6cdbb..c595a6ff2 100644 --- a/tasks/integrated-benchmark/Cargo.toml +++ b/tasks/integrated-benchmark/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pacquet_integrated_benchmark" +name = "pacquet-integrated-benchmark" version = "0.0.0" publish = false authors.workspace = true diff --git a/tasks/micro-benchmark/Cargo.toml b/tasks/micro-benchmark/Cargo.toml index 7a0f7ea0a..cb620dee8 100644 --- a/tasks/micro-benchmark/Cargo.toml +++ b/tasks/micro-benchmark/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pacquet_micro_benchmark" +name = "pacquet-micro-benchmark" version = "0.0.0" publish = false authors.workspace = true @@ -15,8 +15,8 @@ name = "micro-benchmark" path = "src/main.rs" [dependencies] -pacquet_registry = { workspace = true } -pacquet_tarball = { workspace = true } +pacquet-registry = { workspace = true } +pacquet-tarball = { workspace = true } clap = { workspace = true } criterion = { workspace = true } From c6e1a771cff0256300882df4b46a5c20017afd37 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 16 Oct 2023 15:10:55 +0700 Subject: [PATCH 202/210] fix(ci): check all docs --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d05665a0a..8c9b1404d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -115,7 +115,7 @@ jobs: docs: true - name: Run doc - run: RUSTDOCFLAGS='-D warnings' cargo doc -p pacquet_cli + run: RUSTDOCFLAGS='-D warnings' cargo doc test: name: Test From 9f6204f727deadae15ed41ab1db4e104dcb816b5 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 16 Oct 2023 18:34:04 +0700 Subject: [PATCH 203/210] fix(ci): micro-benchmark --- .github/workflows/micro-benchmark.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/micro-benchmark.yml b/.github/workflows/micro-benchmark.yml index cac3d1114..d26db189e 100644 --- a/.github/workflows/micro-benchmark.yml +++ b/.github/workflows/micro-benchmark.yml @@ -32,7 +32,7 @@ jobs: shared-key: micro-benchmark - name: Compile - run: cargo build --release -p pacquet_micro_benchmark + run: cargo build --release --bin=micro-benchmark - name: Sleep for CPU cooldown shell: bash @@ -48,7 +48,7 @@ jobs: ref: ${{ github.event.pull_request.head.sha }} - name: Compile - run: cargo build --release -p pacquet_micro_benchmark + run: cargo build --release --bin=micro-benchmark - name: Sleep for CPU cooldown shell: bash From c25d2b35b2c914de2341b959bb2efd8aee546a64 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 16 Oct 2023 20:16:33 +0700 Subject: [PATCH 204/210] docs: remove redundant comment --- crates/cli/src/cli_args.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/cli/src/cli_args.rs b/crates/cli/src/cli_args.rs index b0898da03..1cc3b56a5 100644 --- a/crates/cli/src/cli_args.rs +++ b/crates/cli/src/cli_args.rs @@ -59,7 +59,6 @@ impl CliArgs { match command { CliCommand::Init => { - // init command throws an error if package.json file exist. PackageManifest::init(&manifest_path()).wrap_err("initialize package.json")?; } CliCommand::Add(args) => args.run(state()?).await?, From 400eb553081082c16aed9b69d268b5de35529cce Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 16 Oct 2023 21:01:49 +0700 Subject: [PATCH 205/210] refactor: rename `package` to `package_name` --- crates/cli/src/cli_args/add.rs | 4 ++-- crates/package-manager/src/add.rs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/cli/src/cli_args/add.rs b/crates/cli/src/cli_args/add.rs index 1189ae264..e2e44e544 100644 --- a/crates/cli/src/cli_args/add.rs +++ b/crates/cli/src/cli_args/add.rs @@ -66,7 +66,7 @@ impl AddDependencyOptions { #[derive(Debug, Args)] pub struct AddArgs { /// Name of the package - pub package: String, + pub package_name: String, /// --save-prod, --save-dev, --save-optional, --save-peer #[clap(flatten)] pub dependency_options: AddDependencyOptions, @@ -94,7 +94,7 @@ impl AddArgs { manifest, lockfile: lockfile.as_ref(), list_dependency_groups: || self.dependency_options.dependency_groups(), - package: &self.package, + package_name: &self.package_name, save_exact: self.save_exact, } .run() diff --git a/crates/package-manager/src/add.rs b/crates/package-manager/src/add.rs index 8705a7589..bd9da4d96 100644 --- a/crates/package-manager/src/add.rs +++ b/crates/package-manager/src/add.rs @@ -29,7 +29,7 @@ where /// Function that creates an iterator [`DependencyGroup`]s. pub list_dependency_groups: ListDependencyGroups, // must be a function because it is called multiple times /// Name of the package to add. - pub package: &'a str, + pub package_name: &'a str, /// Whether `--save-exact` is provided. pub save_exact: bool, // TODO: add `save-exact` to `.npmrc`, merge configs, and remove this } @@ -57,12 +57,12 @@ where manifest, lockfile, list_dependency_groups, - package, + package_name, save_exact, } = self; let latest_version = PackageVersion::fetch_from_registry( - package, + package_name, PackageTag::Latest, // TODO: add support for specifying tags http_client, &config.registry, @@ -73,7 +73,7 @@ where let version_range = latest_version.serialize(save_exact); for dependency_group in list_dependency_groups() { manifest - .add_dependency(package, &version_range, dependency_group) + .add_dependency(package_name, &version_range, dependency_group) .map_err(AddError::AddDependencyToManifest)?; } From bc9a454c62f6f5047f4c48d16ebc7e53c5fe0a7a Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 16 Oct 2023 21:03:34 +0700 Subject: [PATCH 206/210] docs: future plan --- crates/cli/src/cli_args/add.rs | 2 +- crates/package-manager/src/add.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/cli/src/cli_args/add.rs b/crates/cli/src/cli_args/add.rs index e2e44e544..bd381d843 100644 --- a/crates/cli/src/cli_args/add.rs +++ b/crates/cli/src/cli_args/add.rs @@ -66,7 +66,7 @@ impl AddDependencyOptions { #[derive(Debug, Args)] pub struct AddArgs { /// Name of the package - pub package_name: String, + pub package_name: String, // TODO: 1. support version range, 2. multiple arguments, 3. name this `packages` /// --save-prod, --save-dev, --save-optional, --save-peer #[clap(flatten)] pub dependency_options: AddDependencyOptions, diff --git a/crates/package-manager/src/add.rs b/crates/package-manager/src/add.rs index bd9da4d96..6db7d8592 100644 --- a/crates/package-manager/src/add.rs +++ b/crates/package-manager/src/add.rs @@ -29,7 +29,7 @@ where /// Function that creates an iterator [`DependencyGroup`]s. pub list_dependency_groups: ListDependencyGroups, // must be a function because it is called multiple times /// Name of the package to add. - pub package_name: &'a str, + pub package_name: &'a str, // TODO: 1. support version range, 2. multiple arguments, 3. name this `packages` /// Whether `--save-exact` is provided. pub save_exact: bool, // TODO: add `save-exact` to `.npmrc`, merge configs, and remove this } From 7ba09dfc34fec3f1da525abf9a5e7fd79d413f32 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Mon, 16 Oct 2023 21:07:32 +0700 Subject: [PATCH 207/210] docs: remove from fields --- crates/package-manager/src/add.rs | 10 +--------- .../src/create_virtual_dir_by_snapshot.rs | 5 ----- crates/package-manager/src/create_virtual_store.rs | 5 ----- crates/package-manager/src/install.rs | 7 ------- crates/package-manager/src/install_frozen_lockfile.rs | 6 ------ .../package-manager/src/install_package_by_snapshot.rs | 5 ----- .../src/install_package_from_registry.rs | 6 ------ crates/package-manager/src/install_without_lockfile.rs | 5 ----- .../package-manager/src/symlink_direct_dependencies.rs | 3 --- crates/tarball/src/lib.rs | 6 ------ 10 files changed, 1 insertion(+), 57 deletions(-) diff --git a/crates/package-manager/src/add.rs b/crates/package-manager/src/add.rs index 6db7d8592..ac7e22ea0 100644 --- a/crates/package-manager/src/add.rs +++ b/crates/package-manager/src/add.rs @@ -16,22 +16,14 @@ where ListDependencyGroups: Fn() -> DependencyGroupList, DependencyGroupList: IntoIterator, { - /// Shared cache that store downloaded tarballs. pub tarball_cache: &'a Cache, - /// HTTP client to make HTTP requests. pub http_client: &'a Client, - /// Configuration read from `.npmrc`. pub config: &'static Npmrc, - /// Data from the `package.json` file. pub manifest: &'a mut PackageManifest, - /// Data from the `pnpm-lock.yaml` file. pub lockfile: Option<&'a Lockfile>, - /// Function that creates an iterator [`DependencyGroup`]s. pub list_dependency_groups: ListDependencyGroups, // must be a function because it is called multiple times - /// Name of the package to add. pub package_name: &'a str, // TODO: 1. support version range, 2. multiple arguments, 3. name this `packages` - /// Whether `--save-exact` is provided. - pub save_exact: bool, // TODO: add `save-exact` to `.npmrc`, merge configs, and remove this + pub save_exact: bool, // TODO: add `save-exact` to `.npmrc`, merge configs, and remove this } /// Error type of [`Add`]. diff --git a/crates/package-manager/src/create_virtual_dir_by_snapshot.rs b/crates/package-manager/src/create_virtual_dir_by_snapshot.rs index 3ba6eb8e8..d61077645 100644 --- a/crates/package-manager/src/create_virtual_dir_by_snapshot.rs +++ b/crates/package-manager/src/create_virtual_dir_by_snapshot.rs @@ -13,15 +13,10 @@ use std::{ /// This subroutine installs the files from [`cas_paths`](Self::cas_paths) then creates the symlink layout. #[must_use] pub struct CreateVirtualDirBySnapshot<'a> { - /// Path to the virtual store dir (usually canonical paths of `node_modules/.pacquet`). pub virtual_store_dir: &'a Path, - /// CAS files map. pub cas_paths: &'a HashMap, - /// Import method. pub import_method: PackageImportMethod, - /// Key of the package map from the lockfile. pub dependency_path: &'a DependencyPath, - /// Value of the package map from the lockfile. pub package_snapshot: &'a PackageSnapshot, } diff --git a/crates/package-manager/src/create_virtual_store.rs b/crates/package-manager/src/create_virtual_store.rs index c632503b0..f962c026d 100644 --- a/crates/package-manager/src/create_virtual_store.rs +++ b/crates/package-manager/src/create_virtual_store.rs @@ -10,15 +10,10 @@ use std::collections::HashMap; /// This subroutine generates filesystem layout for the virtual store at `node_modules/.pacquet`. #[must_use] pub struct CreateVirtualStore<'a> { - /// Shared cache that store downloaded tarballs. pub tarball_cache: &'a Cache, - /// HTTP client to make HTTP requests. pub http_client: &'a Client, - /// Configuration read from `.npmrc`. pub config: &'static Npmrc, - /// The `packages` object from the lockfile. pub packages: Option<&'a HashMap>, - /// The part of the lockfile that snapshots `package.json`. pub project_snapshot: &'a RootProjectSnapshot, } diff --git a/crates/package-manager/src/install.rs b/crates/package-manager/src/install.rs index 21aa3ee5e..2cb681be3 100644 --- a/crates/package-manager/src/install.rs +++ b/crates/package-manager/src/install.rs @@ -11,19 +11,12 @@ pub struct Install<'a, DependencyGroupList> where DependencyGroupList: IntoIterator, { - /// Shared cache that store downloaded tarballs. pub tarball_cache: &'a Cache, - /// HTTP client to make HTTP requests. pub http_client: &'a Client, - /// Configuration read from `.npmrc`. pub config: &'static Npmrc, - /// Data from the `package.json` file. pub manifest: &'a PackageManifest, - /// Data from the `pnpm-lock.yaml` file. pub lockfile: Option<&'a Lockfile>, - /// List of [`DependencyGroup`]s. pub dependency_groups: DependencyGroupList, - /// Whether `--frozen-lockfile` is specified. pub frozen_lockfile: bool, } diff --git a/crates/package-manager/src/install_frozen_lockfile.rs b/crates/package-manager/src/install_frozen_lockfile.rs index d5c745827..7a2a6774d 100644 --- a/crates/package-manager/src/install_frozen_lockfile.rs +++ b/crates/package-manager/src/install_frozen_lockfile.rs @@ -20,17 +20,11 @@ pub struct InstallFrozenLockfile<'a, DependencyGroupList> where DependencyGroupList: IntoIterator, { - /// Shared cache that store downloaded tarballs. pub tarball_cache: &'a Cache, - /// HTTP client to make HTTP requests. pub http_client: &'a Client, - /// Configuration read from `.npmrc`. pub config: &'static Npmrc, - /// The part of the lockfile that snapshots `package.json`. pub project_snapshot: &'a RootProjectSnapshot, - /// The `packages` object from the lockfile. pub packages: Option<&'a HashMap>, - /// List of [`DependencyGroup`]s. pub dependency_groups: DependencyGroupList, } diff --git a/crates/package-manager/src/install_package_by_snapshot.rs b/crates/package-manager/src/install_package_by_snapshot.rs index d5b166c60..677c2b9d5 100644 --- a/crates/package-manager/src/install_package_by_snapshot.rs +++ b/crates/package-manager/src/install_package_by_snapshot.rs @@ -12,15 +12,10 @@ use std::borrow::Cow; /// then creates the symlink layout for the package. #[must_use] pub struct InstallPackageBySnapshot<'a> { - /// Shared cache that store downloaded tarballs. pub tarball_cache: &'a Cache, - /// HTTP client to make HTTP requests. pub http_client: &'a Client, - /// Configuration read from `.npmrc`. pub config: &'static Npmrc, - /// Key of the package map from the lockfile. pub dependency_path: &'a DependencyPath, - /// Value of the package map from the lockfile. pub package_snapshot: &'a PackageSnapshot, } diff --git a/crates/package-manager/src/install_package_from_registry.rs b/crates/package-manager/src/install_package_from_registry.rs index 45706d5d2..a2a01e87f 100644 --- a/crates/package-manager/src/install_package_from_registry.rs +++ b/crates/package-manager/src/install_package_from_registry.rs @@ -17,17 +17,11 @@ use std::{path::Path, str::FromStr}; /// `node_modules/.pacquet/fastify@1.0.0/node_modules`. #[must_use] pub struct InstallPackageFromRegistry<'a> { - /// Shared cache that store downloaded tarballs. pub tarball_cache: &'a Cache, - /// HTTP client to make HTTP requests. pub http_client: &'a Client, - /// Configuration read from `.npmrc`. pub config: &'static Npmrc, - /// Path to a `node_modules` directory. pub node_modules_dir: &'a Path, - /// Name of the package to be installed. pub name: &'a str, - /// Version range of the package to be installed. pub version_range: &'a str, } diff --git a/crates/package-manager/src/install_without_lockfile.rs b/crates/package-manager/src/install_without_lockfile.rs index 65e2f387a..0d0bb8b39 100644 --- a/crates/package-manager/src/install_without_lockfile.rs +++ b/crates/package-manager/src/install_without_lockfile.rs @@ -20,15 +20,10 @@ use reqwest::Client; /// * Repeat the process for the dependencies of the package. #[must_use] pub struct InstallWithoutLockfile<'a, DependencyGroupList> { - /// Shared cache that store downloaded tarballs. pub tarball_cache: &'a Cache, - /// HTTP client to make HTTP requests. pub http_client: &'a Client, - /// Configuration read from `.npmrc`. pub config: &'static Npmrc, - /// Data from the `package.json` file. pub manifest: &'a PackageManifest, - /// List of [`DependencyGroup`]s. pub dependency_groups: DependencyGroupList, } diff --git a/crates/package-manager/src/symlink_direct_dependencies.rs b/crates/package-manager/src/symlink_direct_dependencies.rs index 2a5ebb305..1d974605c 100644 --- a/crates/package-manager/src/symlink_direct_dependencies.rs +++ b/crates/package-manager/src/symlink_direct_dependencies.rs @@ -15,11 +15,8 @@ pub struct SymlinkDirectDependencies<'a, DependencyGroupList> where DependencyGroupList: IntoIterator, { - /// Configuration read from `.npmrc`. pub config: &'static Npmrc, - /// The part of the lockfile that snapshots `package.json`. pub project_snapshot: &'a RootProjectSnapshot, - /// List of [`DependencyGroup`]s. pub dependency_groups: DependencyGroupList, } diff --git a/crates/tarball/src/lib.rs b/crates/tarball/src/lib.rs index 4f37b9861..09222a56c 100644 --- a/crates/tarball/src/lib.rs +++ b/crates/tarball/src/lib.rs @@ -114,17 +114,11 @@ fn verify_checksum(data: &[u8], integrity: Integrity) -> Result { - /// Shared cache that store downloaded tarballs. pub tarball_cache: &'a Cache, - /// HTTP client to make HTTP requests. pub http_client: &'a Client, - /// Path to the store directory. pub store_dir: &'static Path, - /// Integrity of the tarball. It can be obtained from the registry index. pub package_integrity: &'a str, - /// Unpack size of the tarball. It can be obtained from the registry index. pub package_unpacked_size: Option, - /// URL to the tarball. pub package_url: &'a str, } From 78c4e1c5eeb8372ab7c124e839dbc5d20766237e Mon Sep 17 00:00:00 2001 From: khai96_ Date: Tue, 17 Oct 2023 01:34:58 +0700 Subject: [PATCH 208/210] fix(clippy): windows --- crates/fs/src/lib.rs | 4 ++-- crates/testing-utils/src/fs.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/fs/src/lib.rs b/crates/fs/src/lib.rs index 0e61b409e..08c68721e 100644 --- a/crates/fs/src/lib.rs +++ b/crates/fs/src/lib.rs @@ -1,11 +1,11 @@ -use std::{io, os, path::Path}; +use std::{io, path::Path}; /// Create a symlink to a directory. /// /// The `link` path will be a symbolic link pointing to `original`. pub fn symlink_dir(original: &Path, link: &Path) -> io::Result<()> { #[cfg(unix)] - return os::unix::fs::symlink(original, link); + return std::os::unix::fs::symlink(original, link); #[cfg(windows)] return junction::create(original, link); // junctions instead of symlinks because symlinks may require elevated privileges. } diff --git a/crates/testing-utils/src/fs.rs b/crates/testing-utils/src/fs.rs index 64d571f02..f6b029021 100644 --- a/crates/testing-utils/src/fs.rs +++ b/crates/testing-utils/src/fs.rs @@ -38,7 +38,7 @@ pub fn get_all_folders(root: &std::path::Path) -> Vec { // Helper function to check if a path is a symlink or junction pub fn is_symlink_or_junction(path: &Path) -> io::Result { #[cfg(windows)] - return junction::exists(&path); + return junction::exists(path); #[cfg(not(windows))] return Ok(path.is_symlink()); From 4e8463bf1919378f8db8a74e5fdb81588cc6c7b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kh=E1=BA=A3i?= Date: Tue, 17 Oct 2023 02:17:38 +0700 Subject: [PATCH 209/210] docs(cli): remove a "pacquet" mention Co-authored-by: Zoltan Kochan --- crates/cli/src/cli_args/add.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli/src/cli_args/add.rs b/crates/cli/src/cli_args/add.rs index bd381d843..df7f4beb8 100644 --- a/crates/cli/src/cli_args/add.rs +++ b/crates/cli/src/cli_args/add.rs @@ -71,7 +71,7 @@ pub struct AddArgs { #[clap(flatten)] pub dependency_options: AddDependencyOptions, /// Saved dependencies will be configured with an exact version rather than using - /// pacquet's default semver range operator. + /// the default semver range operator. #[clap(short = 'E', long = "save-exact")] pub save_exact: bool, /// The directory with links to the store (default is node_modules/.pacquet). From 5a7ed6794f24be5ffec4d54af1a735d215713808 Mon Sep 17 00:00:00 2001 From: khai96_ Date: Tue, 17 Oct 2023 02:30:34 +0700 Subject: [PATCH 210/210] docs: future plan --- crates/package-manifest/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/package-manifest/src/lib.rs b/crates/package-manifest/src/lib.rs index 2f6112bc2..2016861ca 100644 --- a/crates/package-manifest/src/lib.rs +++ b/crates/package-manifest/src/lib.rs @@ -192,7 +192,7 @@ impl PackageManifest { pub fn script( &self, command: &str, - if_present: bool, + if_present: bool, // TODO: split this function into 2, one with --if-present, one without ) -> Result, PackageManifestError> { if let Some(script_str) = self .value