Skip to content

Commit

Permalink
new: Fix global executable not working for PowerShell. (#177)
Browse files Browse the repository at this point in the history
* Update paths.

* Add more stuff.

* Fix scripts.

* Fix script.

* Update postinstall.
  • Loading branch information
milesj committed Jul 7, 2022
1 parent a0591db commit c17849c
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 45 deletions.
13 changes: 13 additions & 0 deletions crates/lang-node/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ pub fn find_package_bin(starting_dir: &Path, bin_name: &str) -> Option<PathBuf>
}
}

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)
Expand Down Expand Up @@ -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() {
Expand Down
12 changes: 5 additions & 7 deletions crates/toolchain/src/pms/npm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -180,9 +180,7 @@ impl Installable<NodeTool> for NpmTool {
impl Executable<NodeTool> 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;
Expand Down Expand Up @@ -222,13 +220,13 @@ impl PackageManager<NodeTool> 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?;

Expand Down
7 changes: 2 additions & 5 deletions crates/toolchain/src/pms/pnpm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down Expand Up @@ -120,10 +120,7 @@ impl Installable<NodeTool> for PnpmTool {
impl Executable<NodeTool> 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;
Expand Down
7 changes: 2 additions & 5 deletions crates/toolchain/src/pms/yarn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down Expand Up @@ -163,10 +163,7 @@ impl Installable<NodeTool> for YarnTool {
impl Executable<NodeTool> 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;
Expand Down
4 changes: 1 addition & 3 deletions crates/toolchain/src/tools/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,7 @@ impl NodeTool {
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
{
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)
Expand Down
27 changes: 20 additions & 7 deletions crates/utils/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
8 changes: 1 addition & 7 deletions crates/workspace/src/actions/run_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -24,12 +24,6 @@ async fn create_env_vars(
) -> Result<HashMap<String, String>, 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)?,
Expand Down
34 changes: 23 additions & 11 deletions packages/cli/postinstall.js
Original file line number Diff line number Diff line change
Expand Up @@ -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') {
Expand All @@ -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`));
Expand All @@ -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) {}
}

0 comments on commit c17849c

Please sign in to comment.