diff --git a/Cargo.lock b/Cargo.lock index c1a7a02..c592225 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,6 +40,7 @@ dependencies = [ "natord", "nom", "num_cpus", + "path-absolutize", "predicates", "roff", "rstest", @@ -533,12 +534,36 @@ dependencies = [ "libc", ] +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + [[package]] name = "option-ext" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "path-absolutize" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4af381fe79fa195b4909485d99f73a80792331df0625188e707854f0b3383f5" +dependencies = [ + "path-dedot", +] + +[[package]] +name = "path-dedot" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07ba0ad7e047712414213ff67533e6dd477af0a4e1d14fb52343e53d30ea9397" +dependencies = [ + "once_cell", +] + [[package]] name = "pin-project-lite" version = "0.2.14" diff --git a/Cargo.toml b/Cargo.toml index d63691f..cd67d16 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,7 @@ application = [ "num_cpus", "threadpool", "base64", + "path-absolutize" ] native-runtime = ["which"] eval = [] @@ -57,6 +58,7 @@ threadpool = { version = "1.8", optional = true } base64 = { version = "0.22", optional = true } natord = { version = "1.0", optional = true } roff = { version = "0.2", optional = true } +path-absolutize = { version = "3.1.1", optional = true } [dev-dependencies] insta = "1.30" diff --git a/src/bin/argc/main.rs b/src/bin/argc/main.rs index e558b20..6ab00ac 100644 --- a/src/bin/argc/main.rs +++ b/src/bin/argc/main.rs @@ -7,6 +7,7 @@ use argc::{ CompKind, NativeRuntime, Runtime, Shell, COMPGEN_KIND_SYMBOL, }; use base64::{engine::general_purpose, Engine as _}; +use path_absolutize::Absolutize; use std::{ collections::HashMap, env, @@ -90,29 +91,30 @@ fn run() -> Result { let shell = runtime.shell_path()?; let script_path = normalize_script_path(&args[2]); let (script_dir, script_path) = { - let script_path = fs::canonicalize(&script_path) - .with_context(|| format!("Failed to run '{script_path}'"))?; - let script_dir = script_path.parent().unwrap(); - let script_path = { - let path = script_path.display().to_string(); - if cfg!(windows) && path.starts_with(r"\\?\") { - path[4..].to_string() - } else { - path - } - }; - (script_dir.to_path_buf(), script_path) + let absolute_script_path = Path::new(&script_path) + .absolutize() + .with_context(|| format!("Invalid script path '{script_path}'"))?; + let script_dir = absolute_script_path.parent().ok_or_else(|| { + anyhow!("Unable to retrieve the script dir from '{script_path}'") + })?; + ( + script_dir.to_path_buf(), + absolute_script_path.display().to_string(), + ) }; let mut envs = HashMap::new(); - if is_runner_script(&script_path) { + let cwd = if is_runner_script(&script_path) { if let Some(cwd) = runtime.current_dir() { if env::var("ARGC_PWD").is_err() { envs.insert("ARGC_PWD".to_string(), escape_shell_words(&cwd)); } } - } + Some(script_dir.as_path()) + } else { + None + }; let args = [vec![&script_path], args.iter().skip(3).collect()].concat(); - return run_command(&script_path, &shell, &args, envs, Some(&script_dir)); + return run_command(&script_path, &shell, &args, envs, cwd); } "--argc-create" => { if let Some((_, script_file)) = get_script_path(false) { @@ -458,10 +460,10 @@ eval "$(argc --argc-eval "$0" "$@")" } fn get_script_path(recursive: bool) -> Option<(PathBuf, PathBuf)> { - let candidates = runner_script_names(); + let names = runner_script_names(); let mut dir = env::current_dir().ok()?; loop { - for name in candidates.iter() { + for name in names.iter() { let path = dir.join(name); if path.exists() { return Some((dir, path));