优化: 项目管理阻塞去重 + normalize_path/白名单抽公共

- collect_sample/detect_stack 三处包 spawn_blocking 防 async 阻塞 + bind_directory 补漏一处
- normalize_path 抽公共到 df-project/scan(删 project.rs 本地 + tool_registry inline 闭包)
- tool_registry update_project 复用 crud is_allowed_column(删硬编码白名单,与 CRUD 同源)

Sprint 20 审查 ③④⑤。todo 记 A/B 验证发现的 2 项非阻断(T-09 idea 补偿删级联 / T-10 normalize_path 同步)
This commit is contained in:
2026-06-14 14:21:24 +08:00
parent 3f0839ace1
commit d5a641797c
5 changed files with 61 additions and 34 deletions

View File

@@ -10,6 +10,19 @@ use std::path::Path;
use anyhow::{Context, Result};
/// 规范化路径用于比较:canonicalize 解析绝对规范路径(失败降级),
/// 统一正斜杠 + 小写。防 `C:\a\b` vs `C:/a/b/` 绕过重复检查。
/// 注:仅用于比较,存库保留用户输入的原始可读路径。
pub fn normalize_path(p: &str) -> String {
match Path::new(p).canonicalize() {
Ok(abs) => abs.to_string_lossy().replace('\\', "/").to_lowercase(),
Err(_) => p
.trim_end_matches(['\\', '/'])
.replace('\\', "/")
.to_lowercase(),
}
}
/// 探测目录的技术栈
///
/// 返回去重后的技术栈标签数组(如 `["rust","vue","tauri","typescript"]`)。