mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-30 02:32:09 +08:00
172 lines
5.8 KiB
Rust
172 lines
5.8 KiB
Rust
use super::CmdResult;
|
|
use crate::{
|
|
cmd::StringifyErr as _,
|
|
config::{Config, PrfItem},
|
|
core::{CoreManager, handle, validate::CoreConfigValidator},
|
|
logging,
|
|
utils::{dirs, logging::Type},
|
|
};
|
|
use smartstring::alias::String;
|
|
use tokio::fs;
|
|
|
|
/// 保存profiles的配置
|
|
#[tauri::command]
|
|
pub async fn save_profile_file(index: String, file_data: Option<String>) -> CmdResult {
|
|
let file_data = match file_data {
|
|
Some(d) => d,
|
|
None => return Ok(()),
|
|
};
|
|
|
|
// 在异步操作前获取必要元数据并释放锁
|
|
let (rel_path, is_merge_file) = {
|
|
let profiles = Config::profiles().await;
|
|
let profiles_guard = profiles.latest_arc();
|
|
let item = profiles_guard.get_item(&index).stringify_err()?;
|
|
let is_merge = item.itype.as_ref().is_some_and(|t| t == "merge");
|
|
let path = item.file.clone().ok_or("file field is null")?;
|
|
(path, is_merge)
|
|
};
|
|
|
|
// 读取原始内容(在释放profiles_guard后进行)
|
|
let original_content = PrfItem {
|
|
file: Some(rel_path.clone()),
|
|
..Default::default()
|
|
}
|
|
.read_file()
|
|
.await
|
|
.stringify_err()?;
|
|
|
|
let profiles_dir = dirs::app_profiles_dir().stringify_err()?;
|
|
let file_path = profiles_dir.join(rel_path.as_str());
|
|
let file_path_str = file_path.to_string_lossy().to_string();
|
|
|
|
// 保存新的配置文件
|
|
fs::write(&file_path, &file_data).await.stringify_err()?;
|
|
|
|
logging!(
|
|
info,
|
|
Type::Config,
|
|
"[cmd配置save] 开始验证配置文件: {}, 是否为merge文件: {}",
|
|
file_path_str,
|
|
is_merge_file
|
|
);
|
|
|
|
if is_merge_file {
|
|
return handle_merge_file(&file_path_str, &file_path, &original_content).await;
|
|
}
|
|
|
|
handle_full_validation(&file_path_str, &file_path, &original_content).await
|
|
}
|
|
|
|
async fn restore_original(
|
|
file_path: &std::path::Path,
|
|
original_content: &str,
|
|
) -> Result<(), String> {
|
|
fs::write(file_path, original_content).await.stringify_err()
|
|
}
|
|
|
|
fn is_script_error(err: &str, file_path_str: &str) -> bool {
|
|
file_path_str.ends_with(".js")
|
|
|| err.contains("Script syntax error")
|
|
|| err.contains("Script must contain a main function")
|
|
|| err.contains("Failed to read script file")
|
|
}
|
|
|
|
async fn handle_merge_file(
|
|
file_path_str: &str,
|
|
file_path: &std::path::Path,
|
|
original_content: &str,
|
|
) -> CmdResult {
|
|
logging!(
|
|
info,
|
|
Type::Config,
|
|
"[cmd配置save] 检测到merge文件,只进行语法验证"
|
|
);
|
|
|
|
match CoreConfigValidator::validate_config_file(file_path_str, Some(true)).await {
|
|
Ok((true, _)) => {
|
|
logging!(info, Type::Config, "[cmd配置save] merge文件语法验证通过");
|
|
if let Err(e) = CoreManager::global().update_config().await {
|
|
logging!(
|
|
warn,
|
|
Type::Config,
|
|
"[cmd配置save] 更新整体配置时发生错误: {}",
|
|
e
|
|
);
|
|
} else {
|
|
handle::Handle::refresh_clash();
|
|
}
|
|
Ok(())
|
|
}
|
|
Ok((false, error_msg)) => {
|
|
logging!(
|
|
warn,
|
|
Type::Config,
|
|
"[cmd配置save] merge文件语法验证失败: {}",
|
|
error_msg
|
|
);
|
|
restore_original(file_path, original_content).await?;
|
|
let result = (false, error_msg.clone());
|
|
crate::cmd::validate::handle_yaml_validation_notice(&result, "合并配置文件");
|
|
Ok(())
|
|
}
|
|
Err(e) => {
|
|
logging!(error, Type::Config, "[cmd配置save] 验证过程发生错误: {}", e);
|
|
restore_original(file_path, original_content).await?;
|
|
Err(e.to_string().into())
|
|
}
|
|
}
|
|
}
|
|
|
|
async fn handle_full_validation(
|
|
file_path_str: &str,
|
|
file_path: &std::path::Path,
|
|
original_content: &str,
|
|
) -> CmdResult {
|
|
match CoreConfigValidator::validate_config_file(file_path_str, None).await {
|
|
Ok((true, _)) => {
|
|
logging!(info, Type::Config, "[cmd配置save] 验证成功");
|
|
Ok(())
|
|
}
|
|
Ok((false, error_msg)) => {
|
|
logging!(warn, Type::Config, "[cmd配置save] 验证失败: {}", error_msg);
|
|
restore_original(file_path, original_content).await?;
|
|
|
|
if error_msg.contains("YAML syntax error")
|
|
|| error_msg.contains("Failed to read file:")
|
|
|| (!file_path_str.ends_with(".js") && !is_script_error(&error_msg, file_path_str))
|
|
{
|
|
logging!(
|
|
info,
|
|
Type::Config,
|
|
"[cmd配置save] YAML配置文件验证失败,发送通知"
|
|
);
|
|
let result = (false, error_msg.to_owned());
|
|
crate::cmd::validate::handle_yaml_validation_notice(&result, "YAML配置文件");
|
|
} else if is_script_error(&error_msg, file_path_str) {
|
|
logging!(
|
|
info,
|
|
Type::Config,
|
|
"[cmd配置save] 脚本文件验证失败,发送通知"
|
|
);
|
|
let result = (false, error_msg.to_owned());
|
|
crate::cmd::validate::handle_script_validation_notice(&result, "脚本文件");
|
|
} else {
|
|
logging!(
|
|
info,
|
|
Type::Config,
|
|
"[cmd配置save] 其他类型验证失败,发送一般通知"
|
|
);
|
|
handle::Handle::notice_message("config_validate::error", error_msg.to_owned());
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
Err(e) => {
|
|
logging!(error, Type::Config, "[cmd配置save] 验证过程发生错误: {}", e);
|
|
restore_original(file_path, original_content).await?;
|
|
Err(e.to_string().into())
|
|
}
|
|
}
|
|
}
|