From 8dbf955ce33b7ab68e23e23f1fdffa4259577272 Mon Sep 17 00:00:00 2001 From: John Vandenberg Date: Wed, 11 Sep 2024 19:43:39 +0800 Subject: [PATCH] Split to create a library --- src/lib.rs | 24 +++++++++ src/main.rs | 136 +++------------------------------------------------ src/utils.rs | 119 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+), 128 deletions(-) create mode 100644 src/lib.rs create mode 100644 src/utils.rs diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..99c0095 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,24 @@ +//! pnpm wrapper library. + +use indexmap::IndexMap; +use serde::{Deserialize, Serialize}; + +pub mod error; +pub mod passed_through; +pub mod shell_quoted; +pub mod utils; +pub mod workspace; + +/// Structure of `package.json`. +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] +#[serde(rename_all = "kebab-case")] +pub struct NodeManifest { + #[serde(default)] + pub name: String, + + #[serde(default)] + pub version: String, + + #[serde(default)] + pub scripts: IndexMap, +} diff --git a/src/main.rs b/src/main.rs index bc9639e..d4132a2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,40 +1,24 @@ use clap::Parser; use cli::Cli; use error::{MainError, PnError}; -use indexmap::IndexMap; use pipe_trait::Pipe; -use serde::{Deserialize, Serialize}; use shell_quoted::ShellQuoted; use std::{ env, - ffi::OsString, - fs::File, - io::{self, ErrorKind, Write}, - num::NonZeroI32, + io::{self, Write}, path::Path, - process::{exit, Command, Stdio}, + process::exit, }; use yansi::Color::{Black, Red}; mod cli; -mod error; -mod passed_through; -mod shell_quoted; -mod workspace; -/// Structure of `package.json`. -#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] -#[serde(rename_all = "kebab-case")] -struct NodeManifest { - #[serde(default)] - name: String, - - #[serde(default)] - version: String, - - #[serde(default)] - scripts: IndexMap, -} +use pn::error; +use pn::passed_through; +use pn::shell_quoted; +use pn::utils::*; +use pn::workspace; +use pn::NodeManifest; fn main() { match run() { @@ -113,34 +97,6 @@ fn run() -> Result<(), MainError> { } } -fn run_script(name: &str, command: ShellQuoted, cwd: &Path) -> Result<(), MainError> { - let path_env = create_path_env()?; - let status = Command::new("sh") - .current_dir(cwd) - .env("PATH", path_env) - .arg("-c") - .arg(&command) - .stdin(Stdio::inherit()) - .stdout(Stdio::inherit()) - .stderr(Stdio::inherit()) - .spawn() - .map_err(PnError::SpawnProcessError)? - .wait() - .map_err(PnError::WaitProcessError)? - .code() - .map(NonZeroI32::new); - match status { - Some(None) => return Ok(()), - Some(Some(status)) => PnError::ScriptError { - name: name.to_string(), - status, - }, - None => PnError::UnexpectedTermination { command }, - } - .pipe(MainError::Pn) - .pipe(Err) -} - fn list_scripts( mut stdout: impl Write, script_map: impl IntoIterator, @@ -153,82 +109,6 @@ fn list_scripts( Ok(()) } -fn pass_to_pnpm(args: &[String]) -> Result<(), MainError> { - let status = Command::new("pnpm") - .args(args) - .stdin(Stdio::inherit()) - .stdout(Stdio::inherit()) - .stderr(Stdio::inherit()) - .spawn() - .map_err(PnError::SpawnProcessError)? - .wait() - .map_err(PnError::WaitProcessError)? - .code() - .map(NonZeroI32::new); - Err(match status { - Some(None) => return Ok(()), - Some(Some(status)) => MainError::Sub(status), - None => MainError::Pn(PnError::UnexpectedTermination { - command: ShellQuoted::from_command_and_args("pnpm".into(), args), - }), - }) -} - -fn pass_to_sub(command: ShellQuoted) -> Result<(), MainError> { - let path_env = create_path_env()?; - let status = Command::new("sh") - .env("PATH", path_env) - .arg("-c") - .arg(&command) - .stdin(Stdio::inherit()) - .stdout(Stdio::inherit()) - .stderr(Stdio::inherit()) - .spawn() - .map_err(PnError::SpawnProcessError)? - .wait() - .map_err(PnError::WaitProcessError)? - .code() - .map(NonZeroI32::new); - Err(match status { - Some(None) => return Ok(()), - Some(Some(status)) => MainError::Sub(status), - None => MainError::Pn(PnError::UnexpectedTermination { command }), - }) -} - -fn read_package_manifest(manifest_path: &Path) -> Result { - manifest_path - .pipe(File::open) - .map_err(|error| match error.kind() { - ErrorKind::NotFound => PnError::NoPkgManifest { - file: manifest_path.to_path_buf(), - }, - _ => PnError::FsError { - path: manifest_path.to_path_buf(), - error, - }, - })? - .pipe(serde_json::de::from_reader::<_, NodeManifest>) - .map_err(|err| { - MainError::Pn(PnError::ParseJsonError { - file: manifest_path.to_path_buf(), - message: err.to_string(), - }) - }) -} - -fn create_path_env() -> Result { - let existing_paths = env::var_os("PATH"); - let existing_paths = existing_paths.iter().flat_map(env::split_paths); - Path::new("node_modules") - .join(".bin") - .pipe(std::iter::once) - .chain(existing_paths) - .pipe(env::join_paths) - .map_err(PnError::NodeBinPathError) - .map_err(MainError::from) -} - #[cfg(test)] mod tests { use super::*; diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..d7c2498 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,119 @@ +use crate::{ + error::{MainError, PnError}, + shell_quoted::ShellQuoted, + NodeManifest, +}; +use pipe_trait::Pipe; +use std::{ + env, + ffi::OsString, + fs::File, + io::ErrorKind, + num::NonZeroI32, + path::Path, + process::{Command, Stdio}, +}; + +pub fn run_script(name: &str, command: ShellQuoted, cwd: &Path) -> Result<(), MainError> { + let path_env = create_path_env()?; + let status = Command::new("sh") + .current_dir(cwd) + .env("PATH", path_env) + .arg("-c") + .arg(&command) + .stdin(Stdio::inherit()) + .stdout(Stdio::inherit()) + .stderr(Stdio::inherit()) + .spawn() + .map_err(PnError::SpawnProcessError)? + .wait() + .map_err(PnError::WaitProcessError)? + .code() + .map(NonZeroI32::new); + match status { + Some(None) => return Ok(()), + Some(Some(status)) => PnError::ScriptError { + name: name.to_string(), + status, + }, + None => PnError::UnexpectedTermination { command }, + } + .pipe(MainError::Pn) + .pipe(Err) +} + +pub fn pass_to_pnpm(args: &[String]) -> Result<(), MainError> { + let status = Command::new("pnpm") + .args(args) + .stdin(Stdio::inherit()) + .stdout(Stdio::inherit()) + .stderr(Stdio::inherit()) + .spawn() + .map_err(PnError::SpawnProcessError)? + .wait() + .map_err(PnError::WaitProcessError)? + .code() + .map(NonZeroI32::new); + Err(match status { + Some(None) => return Ok(()), + Some(Some(status)) => MainError::Sub(status), + None => MainError::Pn(PnError::UnexpectedTermination { + command: ShellQuoted::from_command_and_args("pnpm".into(), args), + }), + }) +} + +pub fn pass_to_sub(command: ShellQuoted) -> Result<(), MainError> { + let path_env = create_path_env()?; + let status = Command::new("sh") + .env("PATH", path_env) + .arg("-c") + .arg(&command) + .stdin(Stdio::inherit()) + .stdout(Stdio::inherit()) + .stderr(Stdio::inherit()) + .spawn() + .map_err(PnError::SpawnProcessError)? + .wait() + .map_err(PnError::WaitProcessError)? + .code() + .map(NonZeroI32::new); + Err(match status { + Some(None) => return Ok(()), + Some(Some(status)) => MainError::Sub(status), + None => MainError::Pn(PnError::UnexpectedTermination { command }), + }) +} + +pub fn read_package_manifest(manifest_path: &Path) -> Result { + manifest_path + .pipe(File::open) + .map_err(|error| match error.kind() { + ErrorKind::NotFound => PnError::NoPkgManifest { + file: manifest_path.to_path_buf(), + }, + _ => PnError::FsError { + path: manifest_path.to_path_buf(), + error, + }, + })? + .pipe(serde_json::de::from_reader::<_, NodeManifest>) + .map_err(|err| { + MainError::Pn(PnError::ParseJsonError { + file: manifest_path.to_path_buf(), + message: err.to_string(), + }) + }) +} + +pub fn create_path_env() -> Result { + let existing_paths = env::var_os("PATH"); + let existing_paths = existing_paths.iter().flat_map(env::split_paths); + Path::new("node_modules") + .join(".bin") + .pipe(std::iter::once) + .chain(existing_paths) + .pipe(env::join_paths) + .map_err(PnError::NodeBinPathError) + .map_err(MainError::from) +}