Skip to content

Commit 44dd9cd

Browse files
committed
fix(cli): use a POSIX path probe in sandbox download
Signed-off-by: Eric Curtin <eric.curtin@docker.com>
1 parent 9e004a7 commit 44dd9cd

1 file changed

Lines changed: 38 additions & 4 deletions

File tree

  • crates/openshell-cli/src

‎crates/openshell-cli/src/ssh.rs‎

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1408,6 +1408,19 @@ fn validate_sandbox_source_path(workspace_root: &str, path: &str) -> Result<Stri
14081408
Ok(cleaned)
14091409
}
14101410

1411+
/// Build the remote probe that prints the workspace root, then the resolved
1412+
/// path if it exists. Uses only POSIX `[` and bare `realpath`, because busybox
1413+
/// `realpath` has no `-e` and treats `--` as a file name.
1414+
fn resolve_probe_command(sandbox_path: &str) -> String {
1415+
let operand = if sandbox_path.starts_with('/') {
1416+
sandbox_path.to_string()
1417+
} else {
1418+
format!("./{sandbox_path}")
1419+
};
1420+
let path = shell_escape(&operand);
1421+
format!("pwd -P && if [ -e {path} ]; then realpath {path}; fi")
1422+
}
1423+
14111424
/// Discover the workspace root and resolve every symlink in `sandbox_path` in
14121425
/// one SSH probe, then refuse the result if it lands outside the workspace.
14131426
///
@@ -1422,10 +1435,7 @@ async fn resolve_sandbox_source_path(
14221435
session: &SshSessionConfig,
14231436
sandbox_path: &str,
14241437
) -> Result<String> {
1425-
let resolve_cmd = format!(
1426-
"pwd -P && realpath -e -- {path}",
1427-
path = shell_escape(sandbox_path)
1428-
);
1438+
let resolve_cmd = resolve_probe_command(sandbox_path);
14291439
let output = ssh_run_capture_stdout(session, &resolve_cmd)
14301440
.await
14311441
.wrap_err_with(|| format!("failed to resolve sandbox source path '{sandbox_path}'"))?;
@@ -3080,6 +3090,30 @@ mod tests {
30803090
assert_eq!(lexical_clean_absolute_path("./a"), None);
30813091
}
30823092

3093+
#[test]
3094+
#[cfg(unix)]
3095+
fn resolve_probe_command_is_posix_and_resolves_symlinks() {
3096+
let dir = tempfile::tempdir().unwrap();
3097+
let root = dir.path().canonicalize().unwrap();
3098+
fs::write(root.join("-f"), "x").unwrap();
3099+
std::os::unix::fs::symlink(root.join("-f"), root.join("link")).unwrap();
3100+
let run = |path: &str| {
3101+
let output = Command::new("sh")
3102+
.arg("-c")
3103+
.arg(resolve_probe_command(path))
3104+
.current_dir(&root)
3105+
.output()
3106+
.unwrap();
3107+
assert!(output.status.success());
3108+
String::from_utf8(output.stdout).unwrap()
3109+
};
3110+
let cwd = format!("{}\n", root.display());
3111+
assert!(!resolve_probe_command("a").contains(" -e --"));
3112+
assert_eq!(run("link"), format!("{cwd}{}/-f\n", root.display()));
3113+
assert_eq!(run("-f"), format!("{cwd}{}/-f\n", root.display()));
3114+
assert_eq!(run("missing"), cwd);
3115+
}
3116+
30833117
#[test]
30843118
fn validate_sandbox_source_path_accepts_workspace_paths() {
30853119
let workspace_root = "/workspace/project";

0 commit comments

Comments
 (0)