Skip to main content

plot/lib/logic/
file_toml_config.rs

1use std::{fs, path::Path};
2
3// Importujemy z Twojej biblioteki:
4use crate::lib::logic::{ConfigManifest, tag_time};
5
6// Zakładam, że masz ConfigManifest, który np. posiada pole `job: Vec<JobSpec>`
7// Jeśli korzystasz z Serde, upewnij się, że struktury mają #[derive(Serialize,
8// Deserialize)]
9
10/// Mechanizm odpowiedzialny za zarządzanie wejściem/wyjściem dla plików
11/// konfiguracyjnych TOML.
12pub struct IoConfig;
13
14impl IoConfig {
15	/// Domyślna ścieżka do pliku konfiguracyjnego w projekcie
16	pub const DEFAULT_PATH: &'static str = "./.x-do.toml";
17
18	// ============================================================================
19	// GENEROWANIE ZAWARTOŚCI
20	// ============================================================================
21
22	/// Zwraca domyślną zawartość konfiguracji wygenerowaną na podstawie
23	/// `JobSpec::default()`
24	fn generate_default_content() -> String {
25		// Opcja A (Zalecana, jeśli Twoje struktury używają #[derive(Serialize)]):
26		// let default_manifest = ConfigManifest { job: vec![JobSpec::default()] };
27		// toml::to_string_pretty(&default_manifest).unwrap_or_default()
28
29		// Opcja B (Jeśli jeszcze nie używasz Serde do serializacji,
30		// to ręczny zrzut "na podstawie" JobSpec::default):
31		r#"
32# ============================================================================
33# 【ENG】 x-do Batch Configuration File
34# 【POL】 Plik konfiguracji wsadowej x-do
35# ============================================================================
36
37[[job]]
38id = "default_job"
39name = "snapshot-project"
40description = "【ENG】 Standard Rust project snapshot / 【POL】 Standardowy zrzut projektu Rust"
41quiet_work = true
42
43[job.scan]
44work_path = "."
45patterns = [
46    "./{.rustfmt,Cargo,rust-toolchain,Makefile}.toml&/",
47    "./**/*.rs&/",
48    "!./target/**",
49    "!./temp/**",
50    "!./.git/**",
51    "./.{gitattributes,gitignore}",
52    "./.github/workflows/*.yml&/",
53    "./.vscode/settings.json&/",
54    "./{API,ARCHITECTURE,AUTHORS,CHANGELOG,README,ROADMAP,TODO}.md",
55	"./dist/{**/*,*}.{bat,exe}&/"
56]
57ignore_case = false
58
59[job.spec]
60mode = "m"
61hide_stats = false
62hide_promo = false
63
64[job.spec.trimming]
65# show_page = 1
66# page_size = 20
67
68[job.table_sotc]
69sort_by = "kind"
70sort_order = "asc"
71reverse = false
72structure = "tree"
73columns = ["date", "time", "size", "tree", "icon", "number", "path"]
74trim_page = 1
75more_icons = false
76
77[job.export]
78save_sotc_at = "./target/.cargo-plot/File"
79title_sotc = "Rust Project Snapshot"
80save_cots_at = "./target/.cargo-plot/Docs"
81title_cots = "Rust Project Snapshot"
82"#
83		.to_string()
84	}
85
86	// ============================================================================
87	// ZARZĄDZANIE PLIKIEM (ZAPIS / BACKUP)
88	// ============================================================================
89
90	/// Tworzy plik konfiguracyjny, tylko jeśli ten jeszcze nie istnieje.
91	pub fn default_config_init_if_missing(path: &str) -> Result<(), String> {
92		if !Path::new(path).exists() {
93			Self::default_config_reset_force(path)?;
94			println!("🌱 Utworzono domyślny plik konfiguracyjny: {}", path);
95		}
96		Ok(())
97	}
98
99	/// Tworzy (lub nadpisuje) plik konfiguracyjny twardym resetem do ustawień
100	/// fabrycznych.
101	pub fn default_config_reset_force(path: &str) -> Result<(), String> {
102		let content = Self::generate_default_content();
103		fs::write(path, content).map_err(|e| format!("❌ Błąd zapisu pliku konfiguracyjnego {}: {}", path, e))?;
104		Ok(())
105	}
106
107	/// Bezpieczny reset: zmienia nazwę starego pliku dodając do niego tag
108	/// czasowy, a następnie tworzy nowy ze świeżą konfiguracją.
109	pub fn default_config_reset_safe(path: &str) -> Result<(), String> {
110		if Path::new(path).exists() {
111			let tag = tag_time().0; // Pobiera czas wygenerowany przez Twoją funkcję
112			let backup_path = format!("{}.{}.bak", path, tag);
113
114			fs::rename(path, &backup_path).map_err(|e| format!("❌ Błąd podczas tworzenia kopii zapasowej: {}", e))?;
115
116			println!("📦 Utworzono kopię zapasową starej konfiguracji: {}", backup_path);
117		}
118
119		Self::default_config_reset_force(path)?;
120		println!("🔄 Zresetowano plik konfiguracyjny (utworzono nowy: {})", path);
121
122		Ok(())
123	}
124
125	// ============================================================================
126	// ODCZYT PLIKU (LOADER)
127	// ============================================================================
128
129	/// Ładuje konfigurację z domyślnego miejsca: `./.x-do.toml`
130	pub fn default_config_loader() -> Result<ConfigManifest, String> { Self::config_loader_from(Self::DEFAULT_PATH) }
131
132	/// Ładuje i parsuje konfigurację ze wskazanej ścieżki.
133	pub fn config_loader_from(path: &str) -> Result<ConfigManifest, String> {
134		let content = fs::read_to_string(path).map_err(|e| format!("❌ Nie można odczytać pliku {}: {}", path, e))?;
135
136		// Wymaga crate 'toml' i serde::Deserialize zaimplementowanego na ConfigManifest
137		toml::from_str(&content).map_err(|e| format!("❌ Błąd parsowania struktury TOML w pliku {}: {}", path, e))
138	}
139}