Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ path = "src/main.rs"
name = "just"
test = false

[[bin]]
path = "src/bin/echoargs.rs"
name = "echoargs"
test = false

# The public documentation is minimal and doesn't change between
# platforms, so we only build them for linux on docs.rs to save
# their build machines some cycles.
Expand Down
6 changes: 6 additions & 0 deletions src/bin/echoargs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use std::env;

fn main() {
let args: Vec<String> = env::args().skip(1).collect();
println!("{}", args.join(" "));
}
14 changes: 14 additions & 0 deletions src/command_ext.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use super::*;

pub(crate) trait CommandExt {
fn with_explicit_path(&mut self) -> &mut Command;

fn export(
&mut self,
settings: &Settings,
Expand All @@ -19,6 +21,18 @@ pub(crate) trait CommandExt {
}

impl CommandExt for Command {
fn with_explicit_path(&mut self) -> &mut Command {
// On Windows, set child's path explicitly so that spawned executable
// is located on path before System32 fallback, not the other way around.
// https://blog.rust-lang.org/2022/01/13/Rust-1.58.0/#reduced-windows-command-search-path
#[cfg(windows)]
if let Some(path) = std::env::var_os("Path") {
self.env("Path", path);
}

self
}

fn export(
&mut self,
settings: &Settings,
Expand Down
1 change: 1 addition & 0 deletions src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ impl Executor<'_> {
match self {
Self::Command(interpreter) => {
let mut command = Command::new(&interpreter.command.cooked);
command.with_explicit_path();

if let Some(working_directory) = working_directory {
command.current_dir(working_directory);
Expand Down
4 changes: 3 additions & 1 deletion src/justfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,9 @@ impl<'src> Justfile<'src> {
command.arg(binary);
command
} else {
Command::new(binary)
let mut command = Command::new(binary);
command.with_explicit_path();
command
};

command
Expand Down
1 change: 1 addition & 0 deletions src/platform/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ impl PlatformInterface for Platform {
};

let mut cmd = Command::new(command.as_ref());
cmd.with_explicit_path();

if let Some(working_directory) = working_directory {
cmd.current_dir(working_directory);
Expand Down
1 change: 1 addition & 0 deletions src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ impl<'src> Settings<'src> {
let (command, args) = self.shell(config);

let mut cmd = Command::new(command);
cmd.with_explicit_path();

cmd.args(args);

Expand Down
2 changes: 1 addition & 1 deletion src/subcommand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ impl Subcommand {
.or_else(|| env::var_os("EDITOR"))
.unwrap_or_else(|| "vim".into());

let error = Command::new(&editor)
let error = Command::new(&editor).with_explicit_path()
.current_dir(&search.working_directory)
.arg(&search.justfile)
.status();
Expand Down
2 changes: 2 additions & 0 deletions tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ mod unstable;
mod which_function;
#[cfg(windows)]
mod windows;
#[cfg(windows)]
mod windows_path_resolution;
#[cfg(target_family = "windows")]
mod windows_shell;
mod working_directory;
Expand Down
41 changes: 41 additions & 0 deletions tests/windows_path_resolution.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use super::*;

#[cfg(windows)]
#[test]
fn windows_path_resolution() {

// Goal: Confirm that $PATH entries are respected *before* C:\Windows\System32 when
// locating shell executable. This can happen when PATH is configured to prefer
// Git-for-Windows' bash.exe, and just must not call C:\Windows\System32\bash.exe
// https://github.com/casey/just/issues/2947

// Copy echoargs.exe to temp directory as where.exe, to intentionally match
// the name of an executable in C:\Windows\System32
let mut echoargs_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
echoargs_path.push("target");
echoargs_path.push("debug");
echoargs_path.push("echoargs.exe");
let tmp = tempdir();
let tmp_subdir= tmp.path().join("subdir");
let tmp_subdir_path = tmp_subdir.as_path();
let exe_path = tmp_subdir_path.join("where.exe");
std::fs::create_dir(tmp_subdir_path).expect("Failed to create temp subdirectory");
std::fs::copy(&echoargs_path, &exe_path)
.expect("Failed to copy exe to temp directory");

// Prepend temp directory to PATH
let new_path = tmp_subdir_path.to_str().unwrap().to_owned() + ";" + &env::var("PATH").unwrap();

Test::with_tempdir(tmp)
.shell(false)
.env("Path", &new_path)
.justfile(
r#"
set shell := ['where.exe']
@default:
test_marker
"#,
)
.stdout("test_marker\n")
.run();
}