mirror of
https://github.com/clash-verge-rev/clash-verge-rev
synced 2025-05-05 00:43:44 +08:00
feat: enhance merge config validation and error handling
This commit is contained in:
parent
1a9b0a476b
commit
a4dd4bcc8a
@ -187,24 +187,57 @@ pub async fn save_profile_file(index: String, file_data: Option<String>) -> CmdR
|
||||
}
|
||||
|
||||
// 在异步操作前完成所有文件操作
|
||||
let (file_path, original_content) = {
|
||||
let (file_path, original_content, is_merge_file) = {
|
||||
let profiles = Config::profiles();
|
||||
let profiles_guard = profiles.latest();
|
||||
let item = wrap_err!(profiles_guard.get_item(&index))?;
|
||||
// 确定是否为merge类型文件
|
||||
let is_merge = item.itype.as_ref().map_or(false, |t| t == "merge");
|
||||
let content = wrap_err!(item.read_file())?;
|
||||
let path = item.file.clone().ok_or("file field is null")?;
|
||||
let profiles_dir = wrap_err!(dirs::app_profiles_dir())?;
|
||||
(profiles_dir.join(path), content)
|
||||
(profiles_dir.join(path), content, is_merge)
|
||||
};
|
||||
|
||||
// 保存新的配置文件
|
||||
wrap_err!(fs::write(&file_path, file_data.clone().unwrap()))?;
|
||||
|
||||
let file_path_str = file_path.to_string_lossy();
|
||||
println!("[cmd配置save] 开始验证配置文件: {}", file_path_str);
|
||||
let file_path_str = file_path.to_string_lossy().to_string();
|
||||
println!("[cmd配置save] 开始验证配置文件: {}, 是否为merge文件: {}", file_path_str, is_merge_file);
|
||||
|
||||
// 验证配置文件
|
||||
match CoreManager::global().validate_config_file(&file_path_str).await {
|
||||
// 对于 merge 文件,只进行语法验证,不进行后续内核验证
|
||||
if is_merge_file {
|
||||
println!("[cmd配置save] 检测到merge文件,只进行语法验证");
|
||||
match CoreManager::global().validate_config_file(&file_path_str, Some(true)).await {
|
||||
Ok((true, _)) => {
|
||||
println!("[cmd配置save] merge文件语法验证通过");
|
||||
// 成功后尝试更新整体配置
|
||||
if let Err(e) = CoreManager::global().update_config().await {
|
||||
println!("[cmd配置save] 更新整体配置时发生错误: {}", e);
|
||||
log::warn!(target: "app", "更新整体配置时发生错误: {}", e);
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
Ok((false, error_msg)) => {
|
||||
println!("[cmd配置save] merge文件语法验证失败: {}", error_msg);
|
||||
// 恢复原始配置文件
|
||||
wrap_err!(fs::write(&file_path, original_content))?;
|
||||
// 发送合并文件专用错误通知
|
||||
let result = (false, error_msg.clone());
|
||||
handle_yaml_validation_notice(&result, "合并配置文件");
|
||||
return Ok(());
|
||||
}
|
||||
Err(e) => {
|
||||
println!("[cmd配置save] 验证过程发生错误: {}", e);
|
||||
// 恢复原始配置文件
|
||||
wrap_err!(fs::write(&file_path, original_content))?;
|
||||
return Err(e.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 非merge文件使用完整验证流程
|
||||
match CoreManager::global().validate_config_file(&file_path_str, None).await {
|
||||
Ok((true, _)) => {
|
||||
println!("[cmd配置save] 验证成功");
|
||||
Ok(())
|
||||
@ -214,18 +247,27 @@ pub async fn save_profile_file(index: String, file_data: Option<String>) -> CmdR
|
||||
// 恢复原始配置文件
|
||||
wrap_err!(fs::write(&file_path, original_content))?;
|
||||
|
||||
// 智能判断是否为脚本错误
|
||||
// 智能判断错误类型
|
||||
let is_script_error = file_path_str.ends_with(".js") ||
|
||||
error_msg.contains("Script syntax error") ||
|
||||
error_msg.contains("Script must contain a main function") ||
|
||||
error_msg.contains("Failed to read script file");
|
||||
error_msg.contains("Script syntax error") ||
|
||||
error_msg.contains("Script must contain a main function") ||
|
||||
error_msg.contains("Failed to read script file");
|
||||
|
||||
if is_script_error {
|
||||
if error_msg.contains("YAML syntax error") ||
|
||||
error_msg.contains("Failed to read file:") ||
|
||||
(!file_path_str.ends_with(".js") && !is_script_error) {
|
||||
// 普通YAML错误使用YAML通知处理
|
||||
println!("[cmd配置save] YAML配置文件验证失败,发送通知");
|
||||
let result = (false, error_msg.clone());
|
||||
handle_yaml_validation_notice(&result, "YAML配置文件");
|
||||
} else if is_script_error {
|
||||
// 脚本错误使用专门的通知处理
|
||||
println!("[cmd配置save] 脚本文件验证失败,发送通知");
|
||||
let result = (false, error_msg.clone());
|
||||
handle_script_validation_notice(&result, "脚本文件");
|
||||
} else {
|
||||
// 普通配置错误使用一般通知
|
||||
println!("[cmd配置save] 其他类型验证失败,发送一般通知");
|
||||
handle::Handle::notice_message("config_validate::error", &error_msg);
|
||||
}
|
||||
|
||||
@ -593,7 +635,7 @@ pub fn handle_script_validation_notice(result: &(bool, String), file_type: &str)
|
||||
pub async fn validate_script_file(file_path: String) -> CmdResult<bool> {
|
||||
log::info!(target: "app", "验证脚本文件: {}", file_path);
|
||||
|
||||
match CoreManager::global().validate_config_file(&file_path).await {
|
||||
match CoreManager::global().validate_config_file(&file_path, None).await {
|
||||
Ok(result) => {
|
||||
handle_script_validation_notice(&result, "脚本文件");
|
||||
Ok(result.0) // 返回验证结果布尔值
|
||||
@ -606,3 +648,51 @@ pub async fn validate_script_file(file_path: String) -> CmdResult<bool> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 处理YAML验证相关的所有消息通知
|
||||
/// 统一通知接口,保持消息类型一致性
|
||||
pub fn handle_yaml_validation_notice(result: &(bool, String), file_type: &str) {
|
||||
if !result.0 {
|
||||
let error_msg = &result.1;
|
||||
println!("[通知] 处理{}验证错误: {}", file_type, error_msg);
|
||||
|
||||
// 检查是否为merge文件
|
||||
let is_merge_file = file_type.contains("合并");
|
||||
|
||||
// 根据错误消息内容判断错误类型
|
||||
let status = if error_msg.starts_with("File not found:") {
|
||||
"config_validate::file_not_found"
|
||||
} else if error_msg.starts_with("Failed to read file:") {
|
||||
"config_validate::yaml_read_error"
|
||||
} else if error_msg.starts_with("YAML syntax error:") {
|
||||
if is_merge_file {
|
||||
"config_validate::merge_syntax_error"
|
||||
} else {
|
||||
"config_validate::yaml_syntax_error"
|
||||
}
|
||||
} else if error_msg.contains("mapping values are not allowed") {
|
||||
if is_merge_file {
|
||||
"config_validate::merge_mapping_error"
|
||||
} else {
|
||||
"config_validate::yaml_mapping_error"
|
||||
}
|
||||
} else if error_msg.contains("did not find expected key") {
|
||||
if is_merge_file {
|
||||
"config_validate::merge_key_error"
|
||||
} else {
|
||||
"config_validate::yaml_key_error"
|
||||
}
|
||||
} else {
|
||||
// 如果是其他类型错误,根据文件类型作为一般错误处理
|
||||
if is_merge_file {
|
||||
"config_validate::merge_error"
|
||||
} else {
|
||||
"config_validate::yaml_error"
|
||||
}
|
||||
};
|
||||
|
||||
log::warn!(target: "app", "{} 验证失败: {}", file_type, error_msg);
|
||||
println!("[通知] 发送通知: status={}, msg={}", status, error_msg);
|
||||
handle::Handle::notice_message(status, error_msg);
|
||||
}
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ impl CoreManager {
|
||||
}
|
||||
|
||||
/// 验证指定的配置文件
|
||||
pub async fn validate_config_file(&self, config_path: &str) -> Result<(bool, String)> {
|
||||
pub async fn validate_config_file(&self, config_path: &str, is_merge_file: Option<bool>) -> Result<(bool, String)> {
|
||||
// 检查文件是否存在
|
||||
if !std::path::Path::new(config_path).exists() {
|
||||
let error_msg = format!("File not found: {}", config_path);
|
||||
@ -248,6 +248,12 @@ impl CoreManager {
|
||||
return Ok((false, error_msg));
|
||||
}
|
||||
|
||||
// 如果是合并文件且不是强制验证,执行语法检查但不进行完整验证
|
||||
if is_merge_file.unwrap_or(false) {
|
||||
println!("[core配置验证] 检测到Merge文件,仅进行语法检查: {}", config_path);
|
||||
return self.validate_file_syntax(config_path).await;
|
||||
}
|
||||
|
||||
// 检查是否为脚本文件
|
||||
let is_script = if config_path.ends_with(".js") {
|
||||
true
|
||||
@ -345,7 +351,8 @@ impl CoreManager {
|
||||
Ok(content) => content,
|
||||
Err(err) => {
|
||||
let error_msg = format!("Failed to read script file: {}", err);
|
||||
//handle::Handle::notice_message("config_validate::script_error", &error_msg);
|
||||
log::warn!(target: "app", "脚本语法错误: {}", err);
|
||||
//handle::Handle::notice_message("config_validate::script_syntax_error", &error_msg);
|
||||
return Ok((false, error_msg));
|
||||
}
|
||||
};
|
||||
@ -440,4 +447,34 @@ impl CoreManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 只进行文件语法检查,不进行完整验证
|
||||
async fn validate_file_syntax(&self, config_path: &str) -> Result<(bool, String)> {
|
||||
println!("[core配置语法检查] 开始检查文件: {}", config_path);
|
||||
|
||||
// 读取文件内容
|
||||
let content = match std::fs::read_to_string(config_path) {
|
||||
Ok(content) => content,
|
||||
Err(err) => {
|
||||
let error_msg = format!("Failed to read file: {}", err);
|
||||
println!("[core配置语法检查] 无法读取文件: {}", error_msg);
|
||||
return Ok((false, error_msg));
|
||||
}
|
||||
};
|
||||
|
||||
// 对YAML文件尝试解析,只检查语法正确性
|
||||
println!("[core配置语法检查] 进行YAML语法检查");
|
||||
match serde_yaml::from_str::<serde_yaml::Value>(&content) {
|
||||
Ok(_) => {
|
||||
println!("[core配置语法检查] YAML语法检查通过");
|
||||
Ok((true, String::new()))
|
||||
},
|
||||
Err(err) => {
|
||||
// 使用标准化的前缀,以便错误处理函数能正确识别
|
||||
let error_msg = format!("YAML syntax error: {}", err);
|
||||
println!("[core配置语法检查] YAML语法错误: {}", error_msg);
|
||||
Ok((false, error_msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -451,5 +451,18 @@
|
||||
"File Not Found": "File missing, changes reverted",
|
||||
"Script File Error": "Script file error, changes reverted",
|
||||
"Core Changed Successfully": "Core changed successfully",
|
||||
"Failed to Change Core": "Failed to change core"
|
||||
"Failed to Change Core": "Failed to change core",
|
||||
"YAML Syntax Error": "YAML syntax error, changes reverted",
|
||||
"YAML Read Error": "YAML read error, changes reverted",
|
||||
"YAML Mapping Error": "YAML mapping error, changes reverted",
|
||||
"YAML Key Error": "YAML key error, changes reverted",
|
||||
"YAML Error": "YAML error, changes reverted",
|
||||
"Merge File Syntax Error": "Merge file syntax error, changes reverted",
|
||||
"Merge File Mapping Error": "Merge file mapping error, changes reverted",
|
||||
"Merge File Key Error": "Merge file key error, changes reverted",
|
||||
"Merge File Error": "Merge file error, changes reverted",
|
||||
"Validate YAML File": "Validate YAML File",
|
||||
"Validate Merge File": "Validate Merge File",
|
||||
"Validation Success": "Validation Success",
|
||||
"Validation Failed": "Validation Failed"
|
||||
}
|
||||
|
@ -135,9 +135,9 @@
|
||||
"Hidden": "隐藏代理组",
|
||||
"Group Name Required": "代理组名称不能为空",
|
||||
"Group Name Already Exists": "代理组名称已存在",
|
||||
"Extend Config": "扩展配置",
|
||||
"Extend Config": "扩展覆写配置",
|
||||
"Extend Script": "扩展脚本",
|
||||
"Global Merge": "全局扩展配置",
|
||||
"Global Merge": "全局扩展覆写配置",
|
||||
"Global Script": "全局扩展脚本",
|
||||
"Type": "类型",
|
||||
"Name": "名称",
|
||||
@ -444,5 +444,18 @@
|
||||
"File Not Found": "文件丢失,变更已撤销",
|
||||
"Script File Error": "脚本文件错误,变更已撤销",
|
||||
"Core Changed Successfully": "内核切换成功",
|
||||
"Failed to Change Core": "无法切换内核"
|
||||
"Failed to Change Core": "无法切换内核",
|
||||
"YAML Syntax Error": "YAML语法错误,变更已撤销",
|
||||
"YAML Read Error": "YAML读取错误,变更已撤销",
|
||||
"YAML Mapping Error": "YAML映射错误,变更已撤销",
|
||||
"YAML Key Error": "YAML键错误,变更已撤销",
|
||||
"YAML Error": "YAML错误,变更已撤销",
|
||||
"Merge File Syntax Error": "覆写文件语法错误,变更已撤销",
|
||||
"Merge File Mapping Error": "覆写文件映射错误,变更已撤销",
|
||||
"Merge File Key Error": "覆写文件键错误,变更已撤销",
|
||||
"Merge File Error": "覆写文件错误,变更已撤销",
|
||||
"Validate YAML File": "验证YAML文件",
|
||||
"Validate Merge File": "验证覆写文件",
|
||||
"Validation Success": "验证成功",
|
||||
"Validation Failed": "验证失败"
|
||||
}
|
||||
|
@ -84,6 +84,33 @@ const handleNoticeMessage = (
|
||||
case "config_validate::file_not_found":
|
||||
Notice.error(`${t("File Not Found")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::yaml_syntax_error":
|
||||
Notice.error(`${t("YAML Syntax Error")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::yaml_read_error":
|
||||
Notice.error(`${t("YAML Read Error")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::yaml_mapping_error":
|
||||
Notice.error(`${t("YAML Mapping Error")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::yaml_key_error":
|
||||
Notice.error(`${t("YAML Key Error")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::yaml_error":
|
||||
Notice.error(`${t("YAML Error")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::merge_syntax_error":
|
||||
Notice.error(`${t("Merge File Syntax Error")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::merge_mapping_error":
|
||||
Notice.error(`${t("Merge File Mapping Error")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::merge_key_error":
|
||||
Notice.error(`${t("Merge File Key Error")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::merge_error":
|
||||
Notice.error(`${t("Merge File Error")} ${msg}`);
|
||||
break;
|
||||
case "config_core::change_success":
|
||||
Notice.success(`${t("Core Changed Successfully")}: ${msg}`);
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user