From c17849c04ef7fc649ae16c6bb0c3de063db4bbbd Mon Sep 17 00:00:00 2001 From: Miles Johnson Date: Mon, 4 Jul 2022 21:25:03 -0700 Subject: [PATCH] new: Fix global executable not working for PowerShell. (#177) * Update paths. * Add more stuff. * Fix scripts. * Fix script. * Update postinstall. --- crates/lang-node/src/node.rs | 13 +++++++++ crates/toolchain/src/pms/npm.rs | 12 ++++---- crates/toolchain/src/pms/pnpm.rs | 7 ++--- crates/toolchain/src/pms/yarn.rs | 7 ++--- crates/toolchain/src/tools/node.rs | 4 +-- crates/utils/src/process.rs | 27 ++++++++++++----- crates/workspace/src/actions/run_target.rs | 8 +---- packages/cli/postinstall.js | 34 +++++++++++++++------- 8 files changed, 67 insertions(+), 45 deletions(-) diff --git a/crates/lang-node/src/node.rs b/crates/lang-node/src/node.rs index fa3055c7a76..56e58be5fbb 100644 --- a/crates/lang-node/src/node.rs +++ b/crates/lang-node/src/node.rs @@ -38,6 +38,10 @@ pub fn find_package_bin(starting_dir: &Path, bin_name: &str) -> Option } } +pub fn find_package_manager_bin(install_dir: &Path, bin_name: &str) -> PathBuf { + install_dir.join(get_bin_name_suffix(bin_name, "cmd", false)) +} + pub fn get_bin_name_suffix(name: &str, windows_ext: &str, flat: bool) -> String { if cfg!(windows) { format!("{}.{}", name, windows_ext) @@ -188,6 +192,15 @@ mod tests { ); } + #[test] + #[cfg(windows)] + fn supports_ps1() { + assert_eq!( + get_bin_name_suffix("foo", "ps1", false), + "foo.ps1".to_owned() + ); + } + #[test] #[cfg(windows)] fn supports_exe() { diff --git a/crates/toolchain/src/pms/npm.rs b/crates/toolchain/src/pms/npm.rs index 45c3e6bffe8..bc309e81c33 100644 --- a/crates/toolchain/src/pms/npm.rs +++ b/crates/toolchain/src/pms/npm.rs @@ -29,7 +29,7 @@ impl NpmTool { let install_dir = node.get_install_dir()?.clone(); Ok(NpmTool { - bin_path: install_dir.join(node::get_bin_name_suffix("npm", "cmd", false)), + bin_path: node::find_package_manager_bin(&install_dir, "npm"), config: config.to_owned(), global_install_dir: None, install_dir, @@ -180,9 +180,7 @@ impl Installable for NpmTool { impl Executable for NpmTool { async fn find_bin_path(&mut self, _node: &NodeTool) -> Result<(), ToolchainError> { // If the global has moved, be sure to reference it - let bin_path = self - .get_global_dir()? - .join(node::get_bin_name_suffix("npm", "cmd", false)); + let bin_path = node::find_package_manager_bin(self.get_global_dir()?, "npm"); if bin_path.exists() { self.bin_path = bin_path; @@ -222,13 +220,13 @@ impl PackageManager for NpmTool { exec_args.extend(args); - let bin_dir = toolchain.get_node().get_install_dir()?; - let npx_path = bin_dir.join(node::get_bin_name_suffix("npx", "cmd", false)); + let install_dir = toolchain.get_node().get_install_dir()?; + let npx_path = node::find_package_manager_bin(install_dir, "npx"); Command::new(&npx_path) .args(exec_args) .cwd(&toolchain.workspace_root) - .env("PATH", get_path_env_var(bin_dir)) + .env("PATH", get_path_env_var(install_dir)) .exec_stream_output() .await?; diff --git a/crates/toolchain/src/pms/pnpm.rs b/crates/toolchain/src/pms/pnpm.rs index 12cf14ea214..25d8f39bebf 100644 --- a/crates/toolchain/src/pms/pnpm.rs +++ b/crates/toolchain/src/pms/pnpm.rs @@ -26,7 +26,7 @@ impl PnpmTool { let install_dir = node.get_install_dir()?.clone(); Ok(PnpmTool { - bin_path: install_dir.join(node::get_bin_name_suffix("pnpm", "cmd", false)), + bin_path: node::find_package_manager_bin(&install_dir, "pnpm"), config: config.to_owned(), install_dir, log_target: String::from("moon:toolchain:pnpm"), @@ -120,10 +120,7 @@ impl Installable for PnpmTool { impl Executable for PnpmTool { async fn find_bin_path(&mut self, node: &NodeTool) -> Result<(), ToolchainError> { // If the global has moved, be sure to reference it - let bin_path = node - .get_npm() - .get_global_dir()? - .join(node::get_bin_name_suffix("pnpm", "cmd", false)); + let bin_path = node::find_package_manager_bin(node.get_npm().get_global_dir()?, "pnpm"); if bin_path.exists() { self.bin_path = bin_path; diff --git a/crates/toolchain/src/pms/yarn.rs b/crates/toolchain/src/pms/yarn.rs index d04813f1086..d1c92121d54 100644 --- a/crates/toolchain/src/pms/yarn.rs +++ b/crates/toolchain/src/pms/yarn.rs @@ -26,7 +26,7 @@ impl YarnTool { let install_dir = node.get_install_dir()?.clone(); Ok(YarnTool { - bin_path: install_dir.join(node::get_bin_name_suffix("yarn", "cmd", false)), + bin_path: node::find_package_manager_bin(&install_dir, "yarn"), config: config.to_owned(), install_dir, log_target: String::from("moon:toolchain:yarn"), @@ -163,10 +163,7 @@ impl Installable for YarnTool { impl Executable for YarnTool { async fn find_bin_path(&mut self, node: &NodeTool) -> Result<(), ToolchainError> { // If the global has moved, be sure to reference it - let bin_path = node - .get_npm() - .get_global_dir()? - .join(node::get_bin_name_suffix("yarn", "cmd", false)); + let bin_path = node::find_package_manager_bin(node.get_npm().get_global_dir()?, "yarn"); if bin_path.exists() { self.bin_path = bin_path; diff --git a/crates/toolchain/src/tools/node.rs b/crates/toolchain/src/tools/node.rs index 28baa71b916..eadc5591cb4 100644 --- a/crates/toolchain/src/tools/node.rs +++ b/crates/toolchain/src/tools/node.rs @@ -100,9 +100,7 @@ impl NodeTool { I: IntoIterator, S: AsRef, { - let corepack_path = self - .install_dir - .join(node::get_bin_name_suffix("corepack", "cmd", false)); + let corepack_path = node::find_package_manager_bin(&self.install_dir, "corepack"); Command::new(&corepack_path) .args(args) diff --git a/crates/utils/src/process.rs b/crates/utils/src/process.rs index 54539442fa9..5a9ce04c1a6 100644 --- a/crates/utils/src/process.rs +++ b/crates/utils/src/process.rs @@ -14,10 +14,11 @@ pub use std::process::{ExitStatus, Output, Stdio}; // Based on how Node.js executes Windows commands: // https://github.com/nodejs/node/blob/master/lib/child_process.js#L572 -fn create_windows_cmd() -> (String, TokioCommand) { - let shell = env::var("COMSPEC") - .or_else(|_| env::var("comspec")) - .unwrap_or_else(|_| "cmd.exe".into()); +fn create_windows_cmd(shell: Option<&str>) -> (String, TokioCommand) { + let shell = match shell { + Some(s) => s.to_owned(), + None => env::var("COMSPEC").unwrap_or_else(|_| "cmd.exe".into()), + }; let mut cmd = TokioCommand::new(&shell); @@ -36,8 +37,16 @@ fn create_windows_cmd() -> (String, TokioCommand) { ) } +fn detect_windows_cmd(bin: &str) -> (String, TokioCommand) { + if bin.ends_with(".ps1") { + create_windows_cmd(Some("powershell.exe")) + } else { + create_windows_cmd(None) + } +} + pub fn is_windows_script(bin: &str) -> bool { - bin.ends_with(".cmd") || bin.ends_with(".bat") + bin.ends_with(".cmd") || bin.ends_with(".bat") || bin.ends_with(".ps1") } pub fn output_to_string(data: &[u8]) -> String { @@ -66,11 +75,15 @@ impl Command { // Referencing cmd.exe directly if bin_name == "cmd" || bin_name == "cmd.exe" { - (bin_name, cmd) = create_windows_cmd(); + (bin_name, cmd) = create_windows_cmd(Some("cmd.exe")); + + // Referencing powershell.exe directly + } else if bin_name == "powershell" || bin_name == "powershell.exe" { + (bin_name, cmd) = create_windows_cmd(Some("powershell.exe")); // Referencing a batch script that needs to be ran with cmd.exe } else if is_windows_script(&bin_name) { - (bin_name, cmd) = create_windows_cmd(); + (bin_name, cmd) = detect_windows_cmd(&bin_name); cmd.arg(bin); // Assume a command exists on the system diff --git a/crates/workspace/src/actions/run_target.rs b/crates/workspace/src/actions/run_target.rs index cc0a2307f68..6fca4e69985 100644 --- a/crates/workspace/src/actions/run_target.rs +++ b/crates/workspace/src/actions/run_target.rs @@ -4,7 +4,7 @@ use crate::errors::WorkspaceError; use crate::workspace::Workspace; use moon_cache::RunTargetState; use moon_config::TaskType; -use moon_logger::{color, debug, trace, warn}; +use moon_logger::{color, debug, warn}; use moon_project::{Project, Target, Task}; use moon_terminal::output::{label_checkpoint, Checkpoint}; use moon_toolchain::{get_path_env_var, Executable}; @@ -24,12 +24,6 @@ async fn create_env_vars( ) -> Result, WorkspaceError> { let mut env_vars = HashMap::new(); - trace!( - target: LOG_TARGET, - "Creating {} environment variables", - color::shell("MOON_*") - ); - env_vars.insert( "MOON_CACHE_DIR".to_owned(), path::path_to_string(&workspace.cache.dir)?, diff --git a/packages/cli/postinstall.js b/packages/cli/postinstall.js index 92fd3ad5ed2..2f955d2cecc 100644 --- a/packages/cli/postinstall.js +++ b/packages/cli/postinstall.js @@ -4,15 +4,18 @@ const fs = require('fs'); const path = require('path'); -const platform = - process.platform === 'win32' - ? 'windows' - : process.platform === 'darwin' - ? 'macos' - : process.platform; +const isMoonLocal = + fs.existsSync(path.join(__dirname, '../../.moon')) && + fs.existsSync(path.join(__dirname, '../../crates')); + +const isLinux = process.platform === 'linux'; +const isMacos = process.platform === 'darwin'; +const isWindows = process.platform === 'win32'; + +const platform = isWindows ? 'windows' : isMacos ? 'macos' : process.platform; const parts = [platform, process.arch]; -if (process.platform === 'linux') { +if (isLinux) { const { familySync } = require('detect-libc'); if (familySync() === 'musl') { @@ -22,11 +25,11 @@ if (process.platform === 'linux') { } else { parts.push('gnu'); } -} else if (process.platform === 'win32') { +} else if (isWindows) { parts.push('msvc'); } -const binary = process.platform === 'win32' ? 'moon.exe' : 'moon'; +const binary = isWindows ? 'moon.exe' : 'moon'; const triple = parts.join('-'); const pkgPath = path.dirname(require.resolve(`@moonrepo/core-${triple}/package.json`)); @@ -43,6 +46,15 @@ try { throw new Error(); } } catch { - console.error('Failed to find "moon" binary.'); - // process.exit(1); + console.error(`Failed to find "${binary}" binary.`); + + if (!isMoonLocal) { + process.exit(1); + } +} + +if (isWindows && !isMoonLocal) { + try { + fs.unlinkSync(path.join(__dirname, 'moon')); + } catch (error) {} }