feat: add clash_core config validation & auto-fix to default; fixed "No such file or directory (os error 2)"

This commit is contained in:
wonfen
2025-06-16 20:27:02 +08:00
parent 2a0e1e206e
commit 26acce94a4
6 changed files with 107 additions and 26 deletions

View File

@@ -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::<IVerge>(&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<IVerge> 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<IVerge> 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,

View File

@@ -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);

View File

@@ -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}");

View File

@@ -22,7 +22,7 @@ pub async fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
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),

View File

@@ -286,6 +286,9 @@ pub fn init_config() -> Result<()> {
<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"))?;