diff --git a/src-tauri/src/database/dao/skills.rs b/src-tauri/src/database/dao/skills.rs index 6c91225ca..488fde29d 100644 --- a/src-tauri/src/database/dao/skills.rs +++ b/src-tauri/src/database/dao/skills.rs @@ -235,32 +235,30 @@ impl Database { Ok(()) } - /// 初始化默认的 Skill 仓库(启动时调用,补充缺失的默认仓库) + /// 初始化默认的 Skill 仓库(启动时调用,每个数据库仅执行一次) pub fn init_default_skill_repos(&self) -> Result { - // 获取已有仓库列表 - let existing = self.get_skill_repos()?; - let existing_keys: std::collections::HashSet<(String, String)> = existing - .iter() - .map(|r| (r.owner.clone(), r.name.clone())) - .collect(); + const INITIALIZED_KEY: &str = "default_skill_repos_initialized"; + + if self.get_bool_flag(INITIALIZED_KEY)? { + return Ok(0); + } + + // 兼容升级前已经存在的用户选择,并记录初始化状态,避免以后删空后恢复默认值。 + if !self.get_skill_repos()?.is_empty() { + self.set_setting(INITIALIZED_KEY, "true")?; + return Ok(0); + } - // 获取默认仓库列表 let default_store = crate::services::skill::SkillStore::default(); let mut count = 0; - // 仅插入缺失的默认仓库 for repo in &default_store.repos { - let key = (repo.owner.clone(), repo.name.clone()); - if !existing_keys.contains(&key) { - self.save_skill_repo(repo)?; - count += 1; - log::info!("补充默认 Skill 仓库: {}/{}", repo.owner, repo.name); - } + self.save_skill_repo(repo)?; + count += 1; + log::info!("初始化默认 Skill 仓库: {}/{}", repo.owner, repo.name); } - if count > 0 { - log::info!("补充默认 Skill 仓库完成,新增 {count} 个"); - } + self.set_setting(INITIALIZED_KEY, "true")?; Ok(count) } } diff --git a/src-tauri/src/database/tests.rs b/src-tauri/src/database/tests.rs index 2763f61e4..e6c39dc9b 100644 --- a/src-tauri/src/database/tests.rs +++ b/src-tauri/src/database/tests.rs @@ -151,6 +151,38 @@ fn normalize_default(default: &Option) -> Option { .map(|s| s.trim_matches('\'').trim_matches('"').to_string()) } +#[test] +fn deleted_default_skill_repo_is_not_restored() { + let db = Database::memory().expect("create memory db"); + + assert_eq!(db.init_default_skill_repos().expect("initialize repos"), 4); + for repo in db.get_skill_repos().expect("get initialized repos") { + db.delete_skill_repo(&repo.owner, &repo.name) + .expect("delete repo"); + } + assert!(db.get_skill_repos().expect("get deleted repos").is_empty()); + + assert_eq!( + db.init_default_skill_repos().expect("reinitialize repos"), + 0 + ); + assert!(db.get_skill_repos().expect("get repos").is_empty()); +} + +#[test] +fn existing_skill_repo_selection_is_not_supplemented() { + let db = Database::memory().expect("create memory db"); + let default_store = crate::services::skill::SkillStore::default(); + db.save_skill_repo(&default_store.repos[0]) + .expect("save existing repo"); + + assert_eq!(db.init_default_skill_repos().expect("initialize repos"), 0); + assert_eq!(db.get_skill_repos().expect("get repos").len(), 1); + assert!(db + .get_bool_flag("default_skill_repos_initialized") + .expect("get initialized flag")); +} + #[test] fn schema_migration_sets_user_version_when_missing() { let conn = Connection::open_in_memory().expect("open memory db");