aboutsummaryrefslogtreecommitdiff
path: root/mingling_cli/src
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-08-10 14:40:37 +0800
committer魏曹先生 <1992414357@qq.com>2026-08-10 14:40:37 +0800
commit6b18873666e17ab68ffce799b1707c030166738f (patch)
tree8a32b1524a68ce1591bdc897fd37ac456e0932c9 /mingling_cli/src
parent471d11e12d1bbbf29a0c07a00311ebe5eac893ec (diff)
fix: strip verbatim prefix from canonicalized paths on Windows
Refactor `find_project_root` to use `deverbatim` on canonicalized paths, removing the `\\?\` prefix on Windows to ensure proper path handling.
Diffstat (limited to 'mingling_cli/src')
-rw-r--r--mingling_cli/src/proj_mgr/cmd_class_add.rs24
1 files changed, 23 insertions, 1 deletions
diff --git a/mingling_cli/src/proj_mgr/cmd_class_add.rs b/mingling_cli/src/proj_mgr/cmd_class_add.rs
index 5973252..456ec2f 100644
--- a/mingling_cli/src/proj_mgr/cmd_class_add.rs
+++ b/mingling_cli/src/proj_mgr/cmd_class_add.rs
@@ -54,7 +54,7 @@ pub fn class_add(args: EntryClassAdd) -> Next {
/// Walk upward from `start` to find the first directory containing `.mling`.
fn find_project_root(start: &Path) -> Option<PathBuf> {
- let mut dir = fs::canonicalize(start).ok()?;
+ let mut dir = deverbatim(&fs::canonicalize(start).ok()?);
loop {
if dir.join(".mling").is_dir() {
return Some(dir);
@@ -65,6 +65,28 @@ fn find_project_root(start: &Path) -> Option<PathBuf> {
}
}
+/// Deverbatim a Windows path: strip the `\\?\` prefix that `fs::canonicalize`
+/// may add. On non-Windows platforms this is a no-op.
+///
+/// On Windows, canonical paths sometimes carry a verbatim prefix like
+/// `\\?\C:\...`. This function removes that prefix. For UNC paths such as
+/// `\\?\UNC\server\share`, the prefix is converted back to the conventional
+/// `\\server\share` form.
+fn deverbatim(path: &Path) -> PathBuf {
+ if !cfg!(windows) {
+ return path.to_path_buf();
+ }
+ let as_string = path.to_string_lossy();
+ if let Some(rest) = as_string.strip_prefix(r"\\?\") {
+ // Turns `\\?\UNC\server\share` back into `\\server\share`.
+ if let Some(share) = rest.strip_prefix("UNC\\") {
+ return PathBuf::from(format!(r"\\{share}"));
+ }
+ return PathBuf::from(rest.to_owned());
+ }
+ path.to_path_buf()
+}
+
/// Read `.mling/classes.toml`, find the class template and render it with the
/// name-derived parameters into `<output-dir>/<snake_case>.rs`.
#[chain(routeify)]