Skip to main content

syncbox/config/
mod.rs

1use serde::Deserialize;
2use std::fs;
3use std::path::PathBuf;
4
5// 我们使用 TOML 作为配置文件格式
6// 这个结构体表示整个 syncbox.toml 文件的内容
7#[derive(Deserialize, Debug)]
8pub struct Config {
9    // sync 是一个数组,可以定义多个同步任务
10    pub sync: Vec<SyncTask>,
11}
12
13// 每个同步任务的定义
14#[derive(Deserialize, Debug)]
15pub struct SyncTask {
16    // 任务名称,比如 "my-docs"
17    pub name: String,
18
19    // 源目录路径
20    pub source: PathBuf,
21
22    // 目标目录路径
23    pub target: PathBuf,
24
25    // 可选:要排除的文件或目录(支持 glob 模式)
26    #[serde(default)]
27    pub exclude: Vec<String>,
28
29    #[serde(default = "default_delete_extra")]
30    pub delete_extra: bool,
31
32    #[serde(default)]
33    pub delete_extra_exclude: Vec<String>,
34}
35
36fn default_delete_extra() -> bool {
37    false
38}
39
40impl Config {
41    // 从文件路径加载配置
42    pub fn from_file<P: AsRef<std::path::Path>>(path: P) -> anyhow::Result<Self> {
43        let path = path.as_ref();
44
45        // 1. 检查文件是否存在
46        if !path.exists() {
47            anyhow::bail!("Config file not found: {}", path.display());
48        }
49
50        // 2. 读取文件内容
51        let content = fs::read_to_string(path)
52            .map_err(|e| anyhow::anyhow!("Failed to read config file: {}", e))?;
53
54        // 3. 解析 TOML
55        let config: Config = toml::from_str(&content)
56            .map_err(|e| anyhow::anyhow!("Failed to parse config file: {}", e))?;
57
58        // 4. 返回配置
59        Ok(config)
60    }
61
62    // 根据名称查找一个同步任务
63    pub fn find_task(&self, name: &str) -> Option<&SyncTask> {
64        self.sync.iter().find(|task| task.name == name)
65    }
66}