From bab76dcd111d23b6387ef2919105ef55c91d9768 Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Sat, 24 Oct 2026 10:43:16 -0700 Subject: [PATCH] MCP: the several-roots CLI test keeps a share path a share path The test removed only the \\?\ prefix from the folder it resolved, so a temporary folder on a network share became the relative path UNC\server\share\... . It now removes the \\?\UNC\ prefix first and keeps the two leading backslashes, as file_access::plain does, with a test of both forms. --- apps/designcraft-cli/tests/it/cli.rs | 29 +++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/apps/designcraft-cli/tests/it/cli.rs b/apps/designcraft-cli/tests/it/cli.rs index 8e73fc314..77ee74cff 100644 --- a/apps/designcraft-cli/tests/it/cli.rs +++ b/apps/designcraft-cli/tests/it/cli.rs @@ -347,6 +347,29 @@ fn make_document(path: &std::path::Path) { assert!(path.exists()); } +/// `path` without the `\\?\` or `\\?\UNC\` prefix that `canonicalize` adds on Windows, as the +/// server shows a root (`file_access::plain`). +fn without_verbatim_prefix(path: std::path::PathBuf) -> std::path::PathBuf { + let Some(text) = path.to_str() else { + return path; + }; + if let Some(rest) = text.strip_prefix(r"\\?\UNC\") { + return std::path::PathBuf::from(format!(r"\\{rest}")); + } + match text.strip_prefix(r"\\?\") { + Some(rest) => std::path::PathBuf::from(rest), + None => path, + } +} + +#[test] +fn without_verbatim_prefix_keeps_a_share_a_share() { + let p = |t: &str| without_verbatim_prefix(std::path::PathBuf::from(t)); + assert_eq!(p(r"\\?\UNC\server\share\dir"), std::path::PathBuf::from(r"\\server\share\dir")); + assert_eq!(p(r"\\?\C:\Users\dir"), std::path::PathBuf::from(r"C:\Users\dir")); + assert_eq!(p("/private/var/dir"), std::path::PathBuf::from("/private/var/dir")); +} + #[test] fn mcp_automation_roots_confine_the_server() { let base = std::env::temp_dir().join(format!("dc-cli-roots-{}", std::process::id())); @@ -414,11 +437,7 @@ fn mcp_automation_roots_take_several_folders() { // Resolved, as the server shows the roots (`/var` is `/private/var` on macOS), and without the // `\\?\` prefix that `canonicalize` adds on Windows: the server shows the roots without it, and // Windows does not resolve `..` in a path that has it. - let base = std::fs::canonicalize(base).unwrap(); - let base = match base.to_str().and_then(|t| t.strip_prefix(r"\\?\")) { - Some(rest) => std::path::PathBuf::from(rest), - None => base, - }; + let base = without_verbatim_prefix(std::fs::canonicalize(base).unwrap()); for f in ["in/a.designcraft", "shared/b.designcraft", "outside/secret.designcraft", "parent.designcraft", "in2/c.designcraft"] { make_document(&base.join(f)); }