From 26acce94a40e9203774107187809b0309918d08a Mon Sep 17 00:00:00 2001 From: wonfen Date: Mon, 16 Jun 2025 20:27:02 +0800 Subject: [PATCH] feat: add clash_core config validation & auto-fix to default; fixed "No such file or directory (os error 2)" --- UPDATELOG.md | 17 ++----- src-tauri/src/config/verge.rs | 95 ++++++++++++++++++++++++++++++++++- src-tauri/src/core/core.rs | 13 ++--- src-tauri/src/core/service.rs | 3 +- src-tauri/src/enhance/mod.rs | 2 +- src-tauri/src/utils/init.rs | 3 ++ 6 files changed, 107 insertions(+), 26 deletions(-) diff --git a/UPDATELOG.md b/UPDATELOG.md index 565daf76..136aa2e1 100644 --- a/UPDATELOG.md +++ b/UPDATELOG.md @@ -1,3 +1,8 @@ +## v2.3.1 + +### 🐞 修复问题 + - 增加配置文件校验,修复从古老版本升级上来的"No such file or directory (os error 2)"错误 + ## v2.3.0 **发行代号:御** @@ -5,8 +10,6 @@ 尽管 `external-controller` 密钥现已自动补全默认值且不允许为空,**仍建议手动修改密钥以提高安全性**。 ---- - ### ⚠️ 已知问题 - 仅在 Ubuntu 22.04/24.04、Fedora 41 的 **GNOME 桌面环境** 做过简单测试,不保证其他 Linux 发行版兼容,后续将逐步适配和优化。 @@ -17,8 +20,6 @@ - 已确认窗口状态管理器存在上游缺陷,已暂时移除窗口大小与位置记忆功能。 ---- - ### 🐞 修复问题 - 修复首页“代理模式”快速切换导致的卡死问题 @@ -42,8 +43,6 @@ - 修复 JS 脚本转义特殊字符报错 - 修复 macOS 静默启动时异常启动 Dock 栏图标 ---- - ### ✨ 新增功能 - **Mihomo(Meta) 内核升级至 v1.19.10** @@ -72,8 +71,6 @@ - 新增 Zashboard 一键跳转入口 - 使用系统默认窗口管理器 ---- - ### 🚀 优化改进 - **系统相关:** @@ -112,13 +109,9 @@ - 网络延迟测试替换为 HTTPS 协议:`https://cp.cloudflare.com/generate_204` - 优化 IP 信息获取流程,添加去重机制与轮询检测算法 ---- - - 同步修复翻译错误与不一致项,优化整体语言体验 - 加强语言切换后的页面稳定性,避免加载异常 ---- - ### 🗑️ 移除内容 - 窗口状态管理器(上游存在缺陷) diff --git a/src-tauri/src/config/verge.rs b/src-tauri/src/config/verge.rs index c26fe7bd..603fed2a 100644 --- a/src-tauri/src/config/verge.rs +++ b/src-tauri/src/config/verge.rs @@ -1,6 +1,7 @@ use crate::{ config::{deserialize_encrypted, serialize_encrypted, DEFAULT_PAC}, - utils::{dirs, help, i18n}, + logging, + utils::{dirs, help, i18n, logging::Type}, }; use anyhow::Result; use log::LevelFilter; @@ -232,6 +233,94 @@ pub struct IVergeTheme { } impl IVerge { + /// 有效的clash核心名称 + pub const VALID_CLASH_CORES: &'static [&'static str] = &["verge-mihomo", "verge-mihomo-alpha"]; + + /// 验证并修正配置文件中的clash_core值 + pub fn validate_and_fix_config() -> Result<()> { + let config_path = dirs::verge_path()?; + let mut config = match help::read_yaml::(&config_path) { + Ok(config) => config, + Err(_) => Self::template(), + }; + + let mut needs_fix = false; + + if let Some(ref core) = config.clash_core { + let core_str = core.trim(); + if core_str.is_empty() || !Self::VALID_CLASH_CORES.contains(&core_str) { + logging!( + warn, + Type::Config, + true, + "启动时发现无效的clash_core配置: '{}', 将自动修正为 'verge-mihomo'", + core + ); + config.clash_core = Some("verge-mihomo".to_string()); + needs_fix = true; + } + } else { + logging!( + info, + Type::Config, + true, + "启动时发现未配置clash_core, 将设置为默认值 'verge-mihomo'" + ); + config.clash_core = Some("verge-mihomo".to_string()); + needs_fix = true; + } + + // 修正后保存配置 + if needs_fix { + logging!(info, Type::Config, true, "正在保存修正后的配置文件..."); + help::save_yaml(&config_path, &config, Some("# Clash Verge Config"))?; + logging!( + info, + Type::Config, + true, + "配置文件修正完成,需要重新加载配置" + ); + + Self::reload_config_after_fix(config)?; + } else { + logging!( + info, + Type::Config, + true, + "clash_core配置验证通过: {:?}", + config.clash_core + ); + } + + Ok(()) + } + + /// 配置修正后重新加载配置 + + fn reload_config_after_fix(updated_config: IVerge) -> Result<()> { + use crate::config::Config; + + let config_draft = Config::verge(); + *config_draft.draft() = Box::new(updated_config.clone()); + config_draft.apply(); + + logging!( + info, + Type::Config, + true, + "内存配置已强制更新,新的clash_core: {:?}", + updated_config.clash_core + ); + + Ok(()) + } + + pub fn get_valid_clash_core(&self) -> String { + self.clash_core + .clone() + .unwrap_or_else(|| "verge-mihomo".to_string()) + } + fn get_system_language() -> String { let sys_lang = sys_locale::get_locale() .unwrap_or_else(|| String::from("en")) @@ -503,6 +592,8 @@ pub struct IVergeResponse { impl From for IVergeResponse { fn from(verge: IVerge) -> Self { + // 先获取验证后的clash_core值,避免后续借用冲突 + let valid_clash_core = verge.get_valid_clash_core(); Self { app_log_level: verge.app_log_level, language: verge.language, @@ -534,7 +625,7 @@ impl From for IVergeResponse { proxy_host: verge.proxy_host, theme_setting: verge.theme_setting, web_ui_list: verge.web_ui_list, - clash_core: verge.clash_core, + clash_core: Some(valid_clash_core), hotkeys: verge.hotkeys, auto_close_connection: verge.auto_close_connection, auto_check_update: verge.auto_check_update, diff --git a/src-tauri/src/core/core.rs b/src-tauri/src/core/core.rs index 50255600..70a7748b 100644 --- a/src-tauri/src/core/core.rs +++ b/src-tauri/src/core/core.rs @@ -54,7 +54,7 @@ impl fmt::Display for RunningMode { } } -const CLASH_CORES: [&str; 2] = ["verge-mihomo", "verge-mihomo-alpha"]; +use crate::config::IVerge; impl CoreManager { /// 检查文件是否为脚本文件 @@ -249,8 +249,7 @@ impl CoreManager { config_path ); - let clash_core = { Config::verge().latest().clash_core.clone() }; - let clash_core = clash_core.unwrap_or("verge-mihomo".into()); + let clash_core = Config::verge().latest().get_valid_clash_core(); logging!(info, Type::Config, true, "使用内核: {}", clash_core); let app_handle = handle::Handle::global().app_handle().unwrap(); @@ -442,11 +441,7 @@ impl CoreManager { let app_handle = handle::Handle::global() .app_handle() .ok_or(anyhow::anyhow!("failed to get app handle"))?; - let clash_core = Config::verge() - .latest() - .clash_core - .clone() - .unwrap_or("verge-mihomo".to_string()); + let clash_core = Config::verge().latest().get_valid_clash_core(); let config_dir = dirs::app_home_dir()?; let service_log_dir = dirs::app_home_dir()?.join("logs").join("service"); @@ -804,7 +799,7 @@ impl CoreManager { return Err(error_message.to_string()); } let core: &str = &clash_core.clone().unwrap(); - if !CLASH_CORES.contains(&core) { + if !IVerge::VALID_CLASH_CORES.contains(&core) { let error_message = format!("Clash core invalid name: {}", core); logging!(error, Type::Core, true, "{}", error_message); return Err(error_message); diff --git a/src-tauri/src/core/service.rs b/src-tauri/src/core/service.rs index bc8ff417..6815180f 100644 --- a/src-tauri/src/core/service.rs +++ b/src-tauri/src/core/service.rs @@ -742,8 +742,7 @@ pub(super) async fn start_with_existing_service(config_file: &PathBuf) -> Result log::info!(target:"app", "尝试使用现有服务启动核心 (IPC)"); // logging!(info, Type::Service, true, "尝试使用现有服务启动核心"); - let clash_core = { Config::verge().latest().clash_core.clone() }; - let clash_core = clash_core.unwrap_or("verge-mihomo".into()); + let clash_core = Config::verge().latest().get_valid_clash_core(); let bin_ext = if cfg!(windows) { ".exe" } else { "" }; let clash_bin = format!("{clash_core}{bin_ext}"); diff --git a/src-tauri/src/enhance/mod.rs b/src-tauri/src/enhance/mod.rs index e226880f..000440c1 100644 --- a/src-tauri/src/enhance/mod.rs +++ b/src-tauri/src/enhance/mod.rs @@ -22,7 +22,7 @@ pub async fn enhance() -> (Mapping, Vec, HashMap) { let verge = Config::verge(); let verge = verge.latest(); ( - verge.clash_core.clone(), + Some(verge.get_valid_clash_core()), verge.enable_tun_mode.unwrap_or(false), verge.enable_builtin_enhanced.unwrap_or(true), verge.verge_socks_enabled.unwrap_or(false), diff --git a/src-tauri/src/utils/init.rs b/src-tauri/src/utils/init.rs index 013f1378..3c42986d 100644 --- a/src-tauri/src/utils/init.rs +++ b/src-tauri/src/utils/init.rs @@ -286,6 +286,9 @@ pub fn init_config() -> Result<()> { >::Ok(()) })); + // 验证并修正verge.yaml中的clash_core配置 + crate::log_err!(IVerge::validate_and_fix_config()); + crate::log_err!(dirs::profiles_path().map(|path| { if !path.exists() { help::save_yaml(&path, &IProfiles::template(), Some("# Clash Verge"))?;