From e10f4342f426a6ac39cdc5ff47c3df770aa738ed Mon Sep 17 00:00:00 2001 From: The1111mp Date: Thu, 25 Apr 2024 12:01:58 +0800 Subject: [PATCH] fix: `link` command support using relative paths Signed-off-by: The1111mp --- src/run/npm.rs | 56 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/src/run/npm.rs b/src/run/npm.rs index 73197df..b7bb6c9 100644 --- a/src/run/npm.rs +++ b/src/run/npm.rs @@ -393,6 +393,9 @@ fn get_package_bin_names_for_unlink( Ok(get_package_bin_names(npm_perfix, &tools)) } +/// The link command supports execution from the current package directory without parameters. +/// It also supports execution using the relative directory of the package as a parameter. +/// Finally, the package name is passed in directly, similar to the "install" command. fn get_package_bin_names_for_link(tools: Vec<&OsStr>) -> Result, Error> { if tools.is_empty() { return Ok(get_package_bin_names_from_curdir()?); @@ -404,8 +407,11 @@ fn get_package_bin_names_for_link(tools: Vec<&OsStr>) -> Result, Err let packages = &tools .iter() .map(|name| { - let package = name.to_str().unwrap(); + if PathBuf::from(name).is_relative() { + return *name; + } + let package = name.to_str().unwrap(); match re.find(&package) { None => OsStr::new(package), Some(mat) => OsStr::new(&package[0..(mat.start())]), @@ -413,10 +419,54 @@ fn get_package_bin_names_for_link(tools: Vec<&OsStr>) -> Result, Err }) .collect(); - Ok(get_package_bin_names(&npm_perfix, &packages)) + bin_names_for_link(&npm_perfix, &packages) +} + +fn bin_names_for_link(npm_perfix: &String, packages: &Vec<&OsStr>) -> Result, Error> { + let mut package_bin_names: Vec = vec![]; + for package in packages { + let mut package_json = if PathBuf::from(package).is_relative() { + let mut cur_dir = env::current_dir()?; + cur_dir.push(package); + cur_dir.canonicalize()? + } else { + let mut path = PathBuf::from(npm_perfix); + path.push(package); + path + }; + package_json.push("package.json"); + + let json_str = match read_to_string(&package_json) { + Err(_) => String::from(""), + Ok(v) => v, + }; + + if json_str.is_empty() { + continue; + } + + let json: Value = serde_json::from_str(&json_str).unwrap(); + let bin = &json["bin"]; + + if bin.is_null() { + continue; + } + + if bin.is_string() { + let name = json["name"].as_str().unwrap(); + package_bin_names.push(String::from(name)); + } else { + let keys = json["bin"].as_object().unwrap(); + for (key, _val) in keys { + package_bin_names.push(String::from(key)); + } + } + } + + Ok(package_bin_names) } -/// find package bin names for npm link/unlink command +/// find package bin namesc from current dir for npm link/unlink command fn get_package_bin_names_from_curdir() -> Result, Error> { let mut package_bin_names: Vec = vec![];