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]
56ignore_case = false
57
58[job.spec]
59mode = "m"
60hide_stats = false
61hide_promo = false
62
63[job.spec.trimming]
64# show_page = 1
65# page_size = 20
66
67[job.table_sotc]
68sort_by = "kind"
69sort_order = "asc"
70reverse = false
71structure = "tree"
72columns = ["date", "time", "size", "tree", "icon", "number", "path"]
73trim_page = 1
74more_icons = false
75
76[job.export]
77save_sotc_at = "./target/.cargo-plot/File"
78title_sotc = "Rust Project Snapshot [Structure of the content]"
79save_cots_at = "./target/.cargo-plot/Docs"
80title_cots = "Rust Project Snapshot [Content of the structure]"
81"#
82		.to_string()
83	}
84
85	// ============================================================================
86	// ZARZĄDZANIE PLIKIEM (ZAPIS / BACKUP)
87	// ============================================================================
88
89	/// Tworzy plik konfiguracyjny, tylko jeśli ten jeszcze nie istnieje.
90	pub fn default_config_init_if_missing(path: &str) -> Result<(), String> {
91		if !Path::new(path).exists() {
92			Self::default_config_reset_force(path)?;
93			println!("🌱 Utworzono domyślny plik konfiguracyjny: {}", path);
94		}
95		Ok(())
96	}
97
98	/// Tworzy (lub nadpisuje) plik konfiguracyjny twardym resetem do ustawień
99	/// fabrycznych.
100	pub fn default_config_reset_force(path: &str) -> Result<(), String> {
101		let content = Self::generate_default_content();
102		fs::write(path, content).map_err(|e| format!("❌ Błąd zapisu pliku konfiguracyjnego {}: {}", path, e))?;
103		Ok(())
104	}
105
106	/// Bezpieczny reset: zmienia nazwę starego pliku dodając do niego tag
107	/// czasowy, a następnie tworzy nowy ze świeżą konfiguracją.
108	pub fn default_config_reset_safe(path: &str) -> Result<(), String> {
109		if Path::new(path).exists() {
110			let tag = tag_time().0; // Pobiera czas wygenerowany przez Twoją funkcję
111			let backup_path = format!("{}.{}.bak", path, tag);
112
113			fs::rename(path, &backup_path).map_err(|e| format!("❌ Błąd podczas tworzenia kopii zapasowej: {}", e))?;
114
115			println!("📦 Utworzono kopię zapasową starej konfiguracji: {}", backup_path);
116		}
117
118		Self::default_config_reset_force(path)?;
119		println!("🔄 Zresetowano plik konfiguracyjny (utworzono nowy: {})", path);
120
121		Ok(())
122	}
123
124	// ============================================================================
125	// ODCZYT PLIKU (LOADER)
126	// ============================================================================
127
128	/// Ładuje konfigurację z domyślnego miejsca: `./.x-do.toml`
129	pub fn default_config_loader() -> Result<ConfigManifest, String> { Self::config_loader_from(Self::DEFAULT_PATH) }
130
131	/// Ładuje i parsuje konfigurację ze wskazanej ścieżki.
132	pub fn config_loader_from(path: &str) -> Result<ConfigManifest, String> {
133		let content = fs::read_to_string(path).map_err(|e| format!("❌ Nie można odczytać pliku {}: {}", path, e))?;
134
135		// Wymaga crate 'toml' i serde::Deserialize zaimplementowanego na ConfigManifest
136		toml::from_str(&content).map_err(|e| format!("❌ Błąd parsowania struktury TOML w pliku {}: {}", path, e))
137	}
138}