From 9b5b57a3ac8cf91cd2f66399c1d203f31ad0e0b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=88=AA=E5=AE=87?= <3364451258@qq.com> Date: Thu, 28 May 2026 23:56:50 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20CLI=20=E5=86=99=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E5=8A=A0=E5=8E=9F=E5=AD=90=E6=80=A7=E4=BF=9D=E6=8A=A4=20?= =?UTF-8?q?=E2=80=94=20=E4=BF=9D=E5=AD=98=E5=89=8D=E9=87=8D=E6=96=B0?= =?UTF-8?q?=E8=AF=BB=E5=8F=96=E6=B3=A8=E5=86=8C=E8=A1=A8=E5=AF=B9=E6=AF=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 所有修改命令(add/remove/edit/move/clean/import)在保存前重新读取 注册表,与操作前加载的值对比,不一致则报错退出,防止覆盖其他进程的修改。 Co-Authored-By: Claude Opus 4.7 --- cli/src/main.rs | 51 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 3b0c651..556d35f 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -117,17 +117,28 @@ fn ensure_single_target(system: bool, user: bool) -> &'static str { type SaveFn = fn(Vec) -> Result<(), String>; +fn verify_and_save(target: &str, original: &[String], new_list: Vec) { + let reload = if target == "system" { + core::registry::load_system_paths().unwrap_or_else(|e| exit_err(&e)) + } else { + core::registry::load_user_paths().unwrap_or_else(|e| exit_err(&e)) + }; + if reload != original { + exit_err("注册表已被其他进程修改,请重新执行操作"); + } + let save: SaveFn = if target == "system" { core::registry::save_system_paths } else { core::registry::save_user_paths }; + save(new_list).unwrap_or_else(|e| exit_err(&e)); +} + fn load_and_save(system: bool, f: impl FnOnce(Vec) -> Vec) { let target = ensure_single_target(system, false); - let (list, save): (Vec, SaveFn) = if target == "system" { - (core::registry::load_system_paths().unwrap_or_else(|e| exit_err(&e)), - core::registry::save_system_paths) + let list = if target == "system" { + core::registry::load_system_paths().unwrap_or_else(|e| exit_err(&e)) } else { - (core::registry::load_user_paths().unwrap_or_else(|e| exit_err(&e)), - core::registry::save_user_paths) + core::registry::load_user_paths().unwrap_or_else(|e| exit_err(&e)) }; - let new_list = f(list); - save(new_list).unwrap_or_else(|e| exit_err(&e)); + let new_list = f(list.clone()); + verify_and_save(target, &list, new_list); } // ── 命令实现 ── @@ -174,10 +185,10 @@ fn cmd_remove(index: usize, system: bool) { } else { core::registry::load_user_paths().unwrap_or_else(|e| exit_err(&e)) }; + let original = list.clone(); if index >= list.len() { exit_err(&format!("索引 {index} 超出范围 (共 {} 条)", list.len())); } let removed = list.remove(index); - let save: SaveFn = if target == "system" { core::registry::save_system_paths } else { core::registry::save_user_paths }; - save(list).unwrap_or_else(|e| exit_err(&e)); + verify_and_save(target, &original, list); println!("已删除: {removed}"); core::system::broadcast_env_change(); } @@ -190,9 +201,9 @@ fn cmd_edit(index: usize, new_path: String, system: bool) { core::registry::load_user_paths().unwrap_or_else(|e| exit_err(&e)) }; if index >= list.len() { exit_err(&format!("索引 {index} 超出范围 (共 {} 条)", list.len())); } + let original = list.clone(); let old = std::mem::replace(&mut list[index], new_path.clone()); - let save: SaveFn = if target == "system" { core::registry::save_system_paths } else { core::registry::save_user_paths }; - save(list).unwrap_or_else(|e| exit_err(&e)); + verify_and_save(target, &original, list); println!("已编辑: {old} → {new_path}"); core::system::broadcast_env_change(); } @@ -222,7 +233,7 @@ fn cmd_clean(system: bool, user: bool, dry_run: bool, json_out: bool) { } else { core::registry::load_user_paths().unwrap_or_else(|e| exit_err(&e)) }; - let (kept, removed) = core::registry::clean_paths(list); + let (kept, removed) = core::registry::clean_paths(list.clone()); if json_out { println!("{}", json!({ "kept": kept, "removed": removed, "kept_count": kept.len(), "removed_count": removed.len() }).to_string()); @@ -233,8 +244,7 @@ fn cmd_clean(system: bool, user: bool, dry_run: bool, json_out: bool) { for k in &kept { println!(" ✓ {}", k); } } else { let kept_count = kept.len(); - let save: SaveFn = if target == "system" { core::registry::save_system_paths } else { core::registry::save_user_paths }; - save(kept).unwrap_or_else(|e| exit_err(&e)); + verify_and_save(target, &list, kept); println!("清理完成:移除 {} 条,保留 {} 条", removed.len(), kept_count); core::system::broadcast_env_change(); if !removed.is_empty() { @@ -271,19 +281,24 @@ fn cmd_import(file: String, target: String) { let (sys, usr) = core::fs::import_paths(&file, &content).unwrap_or_else(|e| exit_err(&e)); match target.as_str() { "system" => { - core::registry::save_system_paths(sys).unwrap_or_else(|e| exit_err(&e)); + let orig = core::registry::load_system_paths().unwrap_or_else(|e| exit_err(&e)); + verify_and_save("system", &orig, sys); println!("已导入到系统 PATH"); } "user" => { - core::registry::save_user_paths(usr).unwrap_or_else(|e| exit_err(&e)); + let orig = core::registry::load_user_paths().unwrap_or_else(|e| exit_err(&e)); + verify_and_save("user", &orig, usr); println!("已导入到用户 PATH"); } _ => { - core::registry::save_system_paths(sys).unwrap_or_else(|e| exit_err(&e)); - core::registry::save_user_paths(usr).unwrap_or_else(|e| exit_err(&e)); + let orig_sys = core::registry::load_system_paths().unwrap_or_else(|e| exit_err(&e)); + let orig_usr = core::registry::load_user_paths().unwrap_or_else(|e| exit_err(&e)); + verify_and_save("system", &orig_sys, sys); + verify_and_save("user", &orig_usr, usr); println!("已导入到系统 + 用户 PATH"); } } + core::system::broadcast_env_change(); } fn cmd_export(format: String, output: Option) {