Skip to main content

cgx_engine/
registry.rs

1use std::collections::HashMap;
2use std::path::{Path, PathBuf};
3
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct RepoEntry {
8    pub id: String,
9    pub name: String,
10    pub path: PathBuf,
11    pub db_path: PathBuf,
12    pub indexed_at: String,
13    pub node_count: u64,
14    pub edge_count: u64,
15    #[serde(default)]
16    pub language_breakdown: HashMap<String, f64>,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct Registry {
21    #[serde(default = "default_version")]
22    pub version: u32,
23    #[serde(default)]
24    pub repos: Vec<RepoEntry>,
25}
26
27fn default_version() -> u32 {
28    1
29}
30
31impl Registry {
32    fn path() -> PathBuf {
33        dirs::home_dir()
34            .unwrap_or_else(|| PathBuf::from("."))
35            .join(".cgx")
36            .join("registry.json")
37    }
38
39    pub fn load() -> anyhow::Result<Self> {
40        let path = Self::path();
41        if path.exists() {
42            let content = std::fs::read_to_string(&path)?;
43            let registry: Registry = serde_json::from_str(&content)?;
44            Ok(registry)
45        } else {
46            if let Some(dir) = path.parent() {
47                std::fs::create_dir_all(dir)?;
48            }
49            Ok(Registry {
50                version: 1,
51                repos: Vec::new(),
52            })
53        }
54    }
55
56    pub fn save(&self) -> anyhow::Result<()> {
57        let path = Self::path();
58        if let Some(dir) = path.parent() {
59            std::fs::create_dir_all(dir)?;
60        }
61        let content = serde_json::to_string_pretty(self)?;
62        std::fs::write(&path, content)?;
63        Ok(())
64    }
65
66    pub fn register(&mut self, entry: RepoEntry) {
67        self.repos.retain(|r| r.id != entry.id);
68        self.repos.push(entry);
69    }
70
71    pub fn find_by_path(&self, path: &Path) -> Option<&RepoEntry> {
72        let canonical = path.canonicalize().ok()?;
73        self.repos
74            .iter()
75            .find(|r| r.path.canonicalize().ok().as_ref() == Some(&canonical))
76    }
77
78    pub fn find_by_id(&self, id: &str) -> Option<&RepoEntry> {
79        self.repos.iter().find(|r| r.id == id)
80    }
81}