1use log::{error, info};
2
3use std::{
4 fs,
5 path::{Path, PathBuf},
6};
7
8use clap::Parser;
9use configparser::ini::Ini;
10use dirs::home_dir;
11use once_cell::sync::OnceCell;
12
13pub fn parse_ini_content(content: &str) -> Result<Ini, String> {
88 let mut config = Ini::new();
89 config
90 .read(content.to_string())
91 .map_err(|e| format!("Failed to parse INI: {e:?}"))?;
92 Ok(config)
93}
94
95#[derive(Debug, Default)]
123pub struct GlobalVars {
124 pub config: OnceCell<Ini>,
134
135 obsidian_root_path_dir: OnceCell<PathBuf>,
153
154 obsidian_commit_path: OnceCell<PathBuf>,
180
181 template_commit_date_path: OnceCell<String>,
212
213 template_commit_datetime: OnceCell<String>,
245}
246
247impl GlobalVars {
248 #[must_use]
282 pub fn new() -> Self {
283 info!("[GlobalVars::new()] Creating new GlobalVars with OnceCell default values.");
284 GlobalVars {
285 config: OnceCell::new(),
286
287 obsidian_root_path_dir: OnceCell::new(),
288 obsidian_commit_path: OnceCell::new(),
289
290 template_commit_date_path: OnceCell::new(),
291 template_commit_datetime: OnceCell::new(),
292 }
293 }
294
295 pub fn set_all(&self) -> &Self {
344 info!("[GlobalVars::set_all()] Setting all variables for GlobalVars");
345 let config = get_ini_file();
346
347 info!("[GlobalVars::set_all()]: Setting Config Ini file.");
348 self.config
349 .set(config)
350 .expect("Coulnd't set config in GlobalVars");
351
352 info!("[GlobalVars::set_all()]: Setting Obsidian variables from file.");
353 self.set_obsidian_vars();
354
355 self
356 }
357
358 pub fn get_obsidian_root_path_dir(&self) -> PathBuf {
393 info!("[GlobalVars::get_obsidian_root_path_dir()]: Getting obsidian_root_path_dir.");
394 self.obsidian_root_path_dir
395 .get()
396 .expect("Could not get obsidian_root_path_dir")
397 .clone()
398 }
399
400 pub fn get_obsidian_commit_path(&self) -> PathBuf {
438 info!("[GlobalVars::get_obsidian_commit_path()]: Getting obsidian_commit_path.");
439 self.obsidian_commit_path
440 .get()
441 .expect("Could not get obsidian_commit_path")
442 .clone()
443 }
444
445 pub fn get_template_commit_date_path(&self) -> String {
495 info!("[GlobalVars::get_template_commit_date_path()]: Getting template_commit_date_path.");
496 self.template_commit_date_path
497 .get()
498 .expect("Could not get template_commit_date_path")
499 .clone()
500 }
501
502 pub fn get_template_commit_datetime(&self) -> String {
559 info!("[GlobalVars::get_template_commit_datetime()]: Getting template_commit_datetime.");
560 self.template_commit_datetime
561 .get()
562 .expect("Could not get template_commit_datetime")
563 .clone()
564 }
565
566 fn get_config(&self) -> Ini {
579 info!("[GlobalVars::get_config()] Getting config");
580 self.config
581 .get()
582 .expect("Could not get Config. Config not initialized")
583 .clone()
584 }
585
586 fn get_key_from_section_from_ini(&self, section: &str, key: &str) -> Option<String> {
587 info!(
588 "[GlobalVars::get_key_from_section_from_ini()] Getting key: {key:} from section: {section:}."
589 );
590 self.config
591 .get()
592 .expect("Retrieving the config for commit_path")
593 .get(section, key)
594 }
595
596 fn get_sections_from_config(&self) -> Vec<String> {
597 info!("[GlobalVars::get_sections_from_config()] Getting sections from config");
598 let sections = self.get_config().sections();
599 let sections_len = sections.len(); info!("[GlobalVars::get_sections_from_config()] Checking validity of number of sections.");
602 if sections_len == 2 {
603 sections
604 } else {
605 error!(
606 "[GlobalVars::get_sections_from_config()] Sections Len must be 2, we have: {sections_len:?}"
608 );
609 error!(
610 "[GlobalVars::get_sections_from_config()] These are the sections found: {sections:?}"
611 ); panic!(
613 "[GlobalVars::get_sections_from_config()] config has the wrong number of sections."
614 )
615 }
616 }
617
618 pub fn set_obsidian_vars(&self) {
650 for section in self.get_sections_from_config() {
651 if section == "obsidian" {
652 info!("[GlobalVars::set_obsidian_vars()] Setting 'obsidian' section variables.");
653 self.set_obsidian_root_path_dir(§ion);
654 self.set_obsidian_commit_path(§ion);
655 } else if section == "templates" {
656 info!("[GlobalVars::set_obsidian_vars()] Setting 'templates' section variables.");
657 self.set_templates_commit_date_path(§ion);
658 self.set_templates_datetime(§ion);
659 } else {
660 error!(
661 "[GlobalVars::set_obsidian_vars()] Trying to set other sections is not supported."
662 );
663 panic!(
664 "[GlobalVars::set_obsidian_vars()] Trying to set other sections is not supported."
665 )
666 }
667 }
668 }
669
670 fn set_templates_datetime(&self, section: &str) {
692 info!("[GlobalVars::set_templates_datetime()]: Setting the templates_datetime.");
693 let key = self
694 .get_key_from_section_from_ini(section, "commit_datetime")
695 .expect("Could not get the commit_datetime from INI");
696
697 self.template_commit_datetime
698 .set(key)
699 .expect("Could not set the template_commit_datetime GlobalVars");
700 }
701
702 fn set_templates_commit_date_path(&self, section: &str) {
724 info!(
725 "[GlobalVars::set_templates_commit_date_path()]: Setting the template_commit_date_path."
726 );
727 let key = self
728 .get_key_from_section_from_ini(section, "commit_date_path")
729 .expect("Could not get the commit_date_path from INI");
730
731 self.template_commit_date_path
732 .set(key)
733 .expect("Could not set the template_commit_date_path in GlobalVars");
734 }
735
736 fn set_obsidian_commit_path(&self, section: &str) {
764 let string_path = self
765 .get_key_from_section_from_ini(section, "commit_path")
766 .expect("Could not get commit_path from config");
767
768 let fixed_home = if string_path.contains('~') {
769 info!("[GlobalVars::set_obsidian_commit_path()]: Path does contain: '~'.");
770 set_proper_home_dir(&string_path)
771 } else {
772 info!("[GlobalVars::set_obsidian_commit_path()]: Path does NOT contain: '~'.");
773 string_path
774 };
775
776 let vec_str = fixed_home.split('/');
777
778 let mut path = PathBuf::new();
779
780 info!(
781 "[GlobalVars::set_obsidian_commit_path()]: Pushing strings folders to create PathBuf."
782 );
783 for s in vec_str {
784 path.push(s);
785 }
786 self.obsidian_commit_path
787 .set(path)
788 .expect("Could not set the path for obsidian_root_path_dir");
789 }
790
791 fn set_obsidian_root_path_dir(&self, section: &str) {
825 let string_path = self
826 .get_key_from_section_from_ini(section, "root_path_dir")
827 .expect("Could not get commit_path from config");
828
829 let fixed_home = if string_path.contains('~') {
830 info!("[GlobalVars::set_obsidian_root_path_dir()]: Does contain ~");
831 set_proper_home_dir(&string_path)
832 } else {
833 info!("[GlobalVars::set_obsidian_root_path_dir()]: Does NOT contain ~");
834 string_path
835 };
836
837 let vec_str = fixed_home.split('/');
838 let mut path = PathBuf::new();
839
840 info!(
841 "[GlobalVars::set_obsidian_root_path_dir()]: Pushing '/' to PathBuf for proper path."
842 );
843 path.push("/");
844
845 info!(
846 "[GlobalVars::set_obsidian_root_path_dir()]: Pushing strings folders to create PathBuf."
847 );
848 for s in vec_str {
849 path.push(s);
850 }
851
852 self.obsidian_root_path_dir
853 .set(path)
854 .expect("Could not set the path for obsidian_root_path_dir");
855 }
856}
857
858#[derive(Parser, Debug, Clone)]
883#[command(version, about, long_about = None)]
884#[command(propagate_version = true)]
885#[command(about = "Rusty Commit Saver config", long_about = None)]
886pub struct UserInput {
887 #[arg(short, long)]
905 pub config_ini: Option<String>,
906}
907
908#[must_use]
954pub fn retrieve_config_file_path() -> String {
955 info!(
956 "[UserInput::retrieve_config_file_path()]: retrieving the string path from CLI or default"
957 );
958 let config_path = get_or_default_config_ini_path();
959
960 if Path::new(&config_path).exists() {
961 info!("[UserInput::retrieve_config_file_path()]: config_path exists {config_path:}");
962 } else {
963 error!(
964 "[UserInput::retrieve_config_file_path()]: config_path DOES NOT exists {config_path:}"
965 );
966 panic!(
967 "[UserInput::retrieve_config_file_path()]: config_path DOES NOT exists {config_path:}"
968 );
969 }
970 info!("[UserInput::retrieve_config_file_path()] retrieved config path: {config_path:}");
971 fs::read_to_string(config_path.clone())
972 .unwrap_or_else(|_| panic!("Should have been able to read the file: {config_path:}"))
973}
974
975#[must_use]
994pub fn resolve_config_path(cli_arg: Option<String>, env_var: Option<String>) -> String {
995 if let Some(env_path) = env_var {
997 info!("[resolve_config_path]: Using config from env var.");
998 return if env_path.contains('~') {
999 set_proper_home_dir(&env_path)
1000 } else {
1001 env_path
1002 };
1003 }
1004
1005 if let Some(cfg_str) = cli_arg {
1007 if cfg_str.contains('~') {
1008 info!("[resolve_config_path]: CLI path contains '~'.");
1009 set_proper_home_dir(&cfg_str)
1010 } else {
1011 info!("[resolve_config_path]: CLI path without '~'.");
1012 cfg_str
1013 }
1014 } else {
1015 info!("[resolve_config_path]: Using default path.");
1016 get_default_ini_path()
1017 }
1018}
1019
1020#[must_use]
1021#[cfg_attr(coverage_nightly, coverage(off))]
1022pub fn get_or_default_config_ini_path() -> String {
1023 get_or_default_config_ini_path_with(std::env::var("RUSTY_COMMIT_SAVER_CONFIG").ok(), || {
1024 UserInput::parse().config_ini
1025 })
1026}
1027
1028#[must_use]
1029fn get_or_default_config_ini_path_with<F>(env_var: Option<String>, cli_parser: F) -> String
1030where
1031 F: FnOnce() -> Option<String>,
1032{
1033 info!("[get_or_default_config_ini_path()]: Parsing CLI inputs.");
1034
1035 let cli_arg = if env_var.is_some() {
1036 None } else {
1038 cli_parser()
1039 };
1040
1041 let config_path = resolve_config_path(cli_arg, env_var);
1042 info!("[get_or_default_config_ini_path()]: Config path found: {config_path:}");
1043 config_path
1044}
1045
1046#[must_use]
1081pub fn get_default_ini_path() -> String {
1082 info!("[get_default_ini_path()]: Getting default ini file.");
1083 let cfg_str = "~/.config/rusty-commit-saver/rusty-commit-saver.ini".to_string();
1084 set_proper_home_dir(&cfg_str)
1085}
1086
1087#[must_use]
1131pub fn get_ini_file() -> Ini {
1132 info!("[get_ini_file()]: Retrieving the INI File");
1133 let content_ini = retrieve_config_file_path();
1134 let mut config = Ini::new();
1135 config
1136 .read(content_ini)
1137 .expect("Could not read the INI file!");
1138
1139 info!("[get_ini_file()]: This is the INI File:\n\n{config:?}");
1140 config
1141}
1142
1143fn set_proper_home_dir(cfg_str: &str) -> String {
1184 info!("[set_proper_home_dir()]: Changing the '~' to full home directory.");
1185 let home_dir = home_dir()
1186 .expect("Could not get home_dir")
1187 .into_os_string()
1188 .into_string()
1189 .expect("Could not convert home_dir from OsString to String");
1190
1191 cfg_str.replace('~', &home_dir)
1192}
1193
1194#[cfg(test)]
1195#[cfg_attr(coverage_nightly, coverage(off))]
1196mod global_vars_tests {
1197 use super::*;
1198 use std::panic::{self, AssertUnwindSafe};
1199
1200 #[test]
1201 fn test_global_vars_new() {
1202 let global_vars = GlobalVars::new();
1203
1204 assert!(global_vars.config.get().is_none());
1205 }
1206
1207 #[test]
1208 fn test_global_vars_default() {
1209 let global_vars = GlobalVars::default();
1210
1211 assert!(global_vars.config.get().is_none());
1212 }
1213
1214 #[test]
1215 fn test_get_sections_from_config_valid() {
1216 let mut config = Ini::new();
1217 config.set("obsidian", "root_path_dir", Some("/tmp/test".to_string()));
1218 config.set(
1219 "templates",
1220 "commit_date_path",
1221 Some("%Y-%m-%d".to_string()),
1222 );
1223
1224 let global_vars = GlobalVars::new();
1225 global_vars.config.set(config).unwrap();
1226
1227 let sections = global_vars.get_sections_from_config();
1228
1229 assert_eq!(sections.len(), 2);
1230 assert!(sections.contains(&"obsidian".to_string()));
1231 assert!(sections.contains(&"templates".to_string()));
1232 }
1233
1234 #[test]
1235 fn test_get_sections_from_config_invalid_count() {
1236 let mut config = Ini::new();
1237 config.set("only_one_section", "key", Some("value".to_string()));
1238
1239 let global_vars = GlobalVars::new();
1240 global_vars.config.set(config).unwrap();
1241
1242 let result =
1243 panic::catch_unwind(AssertUnwindSafe(|| global_vars.get_sections_from_config()));
1244
1245 assert!(result.is_err(), "Expected panic for invalid section count");
1246
1247 let panic_info = result.unwrap_err();
1249 let msg = panic_info
1250 .downcast_ref::<&str>()
1251 .expect("Panic message should be &str");
1252 assert!(
1253 msg.contains("wrong number of sections"),
1254 "Unexpected panic message: {msg}"
1255 );
1256 }
1257
1258 #[test]
1259 fn test_get_sections_from_config_panics_with_zero_sections() {
1260 let config = Ini::new();
1261
1262 let global_vars = GlobalVars::new();
1263 global_vars.config.set(config).unwrap();
1264
1265 let result =
1266 panic::catch_unwind(AssertUnwindSafe(|| global_vars.get_sections_from_config()));
1267
1268 assert!(result.is_err(), "Expected panic for zero sections");
1269 }
1270
1271 #[test]
1272 fn test_get_sections_from_config_panics_with_three_sections() {
1273 let mut config = Ini::new();
1274 config.set("obsidian", "root_path_dir", Some("/tmp/test".to_string()));
1275 config.set("templates", "commit_date_path", Some("%Y.md".to_string()));
1276 config.set("extra", "key", Some("value".to_string()));
1277
1278 let global_vars = GlobalVars::new();
1279 global_vars.config.set(config).unwrap();
1280
1281 let result =
1282 panic::catch_unwind(AssertUnwindSafe(|| global_vars.get_sections_from_config()));
1283
1284 assert!(result.is_err(), "Expected panic for three sections");
1285 }
1286
1287 #[test]
1288 fn test_get_key_from_section_from_ini_exists() {
1289 let mut config = Ini::new();
1290 config.set(
1291 "obsidian",
1292 "root_path_dir",
1293 Some("/home/user/Obsidian".to_string()),
1294 );
1295
1296 let global_vars = GlobalVars::new();
1297 global_vars.config.set(config).unwrap();
1298
1299 let result = global_vars.get_key_from_section_from_ini("obsidian", "root_path_dir");
1300
1301 assert_eq!(result, Some("/home/user/Obsidian".to_string()));
1302 }
1303
1304 #[test]
1305 fn test_get_key_from_section_from_ini_not_exists() {
1306 let mut config = Ini::new();
1307 config.set("obsidian", "other_key", Some("value".to_string()));
1308
1309 let global_vars = GlobalVars::new();
1310 global_vars.config.set(config).unwrap();
1311
1312 let result = global_vars.get_key_from_section_from_ini("obsidian", "non_existent_key");
1313
1314 assert_eq!(result, None);
1315 }
1316
1317 #[test]
1318 fn test_get_config() {
1319 let mut config = Ini::new();
1320 config.set("test", "key", Some("value".to_string()));
1321
1322 let global_vars = GlobalVars::new();
1323 global_vars.config.set(config.clone()).unwrap();
1324
1325 let retrieved_config = global_vars.get_config();
1326
1327 assert_eq!(
1328 retrieved_config.get("test", "key"),
1329 Some("value".to_string())
1330 );
1331 }
1332
1333 #[test]
1334 fn test_set_obsidian_root_path_dir_with_tilde() {
1335 let mut config = Ini::new();
1336 config.set(
1337 "obsidian",
1338 "root_path_dir",
1339 Some("~/Documents/Obsidian".to_string()),
1340 );
1341 config.set(
1342 "templates",
1343 "commit_date_path",
1344 Some("%Y-%m-%d".to_string()),
1345 );
1346 config.set("templates", "commit_datetime", Some("%Y-%m-%d".to_string()));
1347
1348 let global_vars = GlobalVars::new();
1349 global_vars.config.set(config).unwrap();
1350 global_vars.set_obsidian_root_path_dir("obsidian");
1351
1352 let result = global_vars.get_obsidian_root_path_dir();
1353
1354 assert!(!result.to_string_lossy().contains('~'));
1356 assert!(result.to_string_lossy().starts_with('/'));
1358 assert!(result.to_string_lossy().ends_with("Obsidian"));
1360 }
1361
1362 #[test]
1363 fn test_set_obsidian_root_path_dir_absolute_path() {
1364 let mut config = Ini::new();
1365 config.set(
1366 "obsidian",
1367 "root_path_dir",
1368 Some("/absolute/path/Obsidian".to_string()),
1369 );
1370 config.set(
1371 "templates",
1372 "commit_date_path",
1373 Some("%Y-%m-%d".to_string()),
1374 );
1375 config.set("templates", "commit_datetime", Some("%Y-%m-%d".to_string()));
1376
1377 let global_vars = GlobalVars::new();
1378 global_vars.config.set(config).unwrap();
1379 global_vars.set_obsidian_root_path_dir("obsidian");
1380
1381 let result = global_vars.get_obsidian_root_path_dir();
1382
1383 assert!(result.to_string_lossy().contains("/absolute/path/Obsidian"));
1385 }
1386
1387 #[test]
1388 fn test_set_obsidian_commit_path_with_tilde() {
1389 let mut config = Ini::new();
1390 config.set(
1391 "obsidian",
1392 "commit_path",
1393 Some("~/Diaries/Commits".to_string()),
1394 );
1395 config.set(
1396 "templates",
1397 "commit_date_path",
1398 Some("%Y-%m-%d".to_string()),
1399 );
1400 config.set("templates", "commit_datetime", Some("%Y-%m-%d".to_string()));
1401
1402 let global_vars = GlobalVars::new();
1403 global_vars.config.set(config).unwrap();
1404 global_vars.set_obsidian_commit_path("obsidian");
1405
1406 let result = global_vars.get_obsidian_commit_path();
1407
1408 assert!(!result.to_string_lossy().contains('~'));
1410 assert!(result.to_string_lossy().ends_with("Commits"));
1412 }
1413
1414 #[test]
1415 fn test_set_obsidian_commit_path_absolute_path() {
1416 let mut config = Ini::new();
1417 config.set(
1418 "obsidian",
1419 "commit_path",
1420 Some("absolute/Diaries/Commits".to_string()),
1421 );
1422 config.set(
1423 "templates",
1424 "commit_date_path",
1425 Some("%Y-%m-%d".to_string()),
1426 );
1427 config.set("templates", "commit_datetime", Some("%Y-%m-%d".to_string()));
1428
1429 let global_vars = GlobalVars::new();
1430 global_vars.config.set(config).unwrap();
1431 global_vars.set_obsidian_commit_path("obsidian");
1432
1433 let result = global_vars.get_obsidian_commit_path();
1434
1435 assert!(result.to_string_lossy().contains("absolute"));
1438 assert!(result.to_string_lossy().ends_with("Commits"));
1439 }
1440
1441 #[test]
1442 fn test_set_templates_commit_date_path() {
1443 let mut config = Ini::new();
1444 config.set(
1445 "templates",
1446 "commit_date_path",
1447 Some("%Y/%m-%B/%F.md".to_string()),
1448 );
1449 config.set("templates", "commit_datetime", Some("%Y-%m-%d".to_string()));
1450
1451 let global_vars = GlobalVars::new();
1452 global_vars.config.set(config).unwrap();
1453 global_vars.set_templates_commit_date_path("templates");
1454
1455 let result = global_vars.get_template_commit_date_path();
1456
1457 assert_eq!(result, "%Y/%m-%B/%F.md");
1458 }
1459
1460 #[test]
1461 fn test_set_templates_datetime() {
1462 let mut config = Ini::new();
1463 config.set(
1464 "templates",
1465 "commit_datetime",
1466 Some("%Y-%m-%d %H:%M:%S".to_string()),
1467 );
1468
1469 let global_vars = GlobalVars::new();
1470 global_vars.config.set(config).unwrap();
1471 global_vars.set_templates_datetime("templates");
1472
1473 let result = global_vars.get_template_commit_datetime();
1474
1475 assert_eq!(result, "%Y-%m-%d %H:%M:%S");
1476 }
1477
1478 #[test]
1479 fn test_set_obsidian_vars_both_sections() {
1480 let mut config = Ini::new();
1481 config.set(
1482 "obsidian",
1483 "root_path_dir",
1484 Some("/home/user/Obsidian".to_string()),
1485 );
1486 config.set(
1487 "obsidian",
1488 "commit_path",
1489 Some("Diaries/Commits".to_string()),
1490 );
1491 config.set(
1492 "templates",
1493 "commit_date_path",
1494 Some("%Y-%m-%d.md".to_string()),
1495 );
1496 config.set(
1497 "templates",
1498 "commit_datetime",
1499 Some("%Y-%m-%d %H:%M:%S".to_string()),
1500 );
1501
1502 let global_vars = GlobalVars::new();
1503 global_vars.config.set(config).unwrap();
1504
1505 global_vars.set_obsidian_vars();
1507
1508 let root_path = global_vars.get_obsidian_root_path_dir();
1510 let commit_path = global_vars.get_obsidian_commit_path();
1511 let date_path = global_vars.get_template_commit_date_path();
1512 let datetime = global_vars.get_template_commit_datetime();
1513
1514 assert!(root_path.to_string_lossy().contains("Obsidian"));
1515 assert!(commit_path.to_string_lossy().contains("Commits"));
1516 assert_eq!(date_path, "%Y-%m-%d.md");
1517 assert_eq!(datetime, "%Y-%m-%d %H:%M:%S");
1518 }
1519
1520 #[test]
1521 #[should_panic(expected = "Trying to set other sections is not supported")]
1522 fn test_set_obsidian_vars_invalid_section() {
1523 let mut config = Ini::new();
1524 config.set("invalid_section", "key", Some("value".to_string()));
1526 config.set(
1527 "templates",
1528 "commit_date_path",
1529 Some("%Y-%m-%d.md".to_string()),
1530 );
1531 config.set(
1532 "templates",
1533 "commit_datetime",
1534 Some("%Y-%m-%d %H:%M".to_string()),
1535 );
1536
1537 let global_vars = GlobalVars::new();
1538 global_vars.config.set(config).unwrap();
1539
1540 global_vars.set_obsidian_vars();
1542 }
1543
1544 #[test]
1545 fn test_set_all_integration() {
1546 use std::io::Write;
1547 use tempfile::NamedTempFile;
1548
1549 let mut temp_file = NamedTempFile::new().unwrap();
1551 writeln!(temp_file, "[obsidian]").unwrap();
1552 writeln!(temp_file, "root_path_dir=/tmp/test_obsidian").unwrap();
1553 writeln!(temp_file, "commit_path=TestDiaries/TestCommits").unwrap();
1554 writeln!(temp_file, "[templates]").unwrap();
1555 writeln!(temp_file, "commit_date_path=%Y-%m-%d.md").unwrap();
1556 writeln!(temp_file, "commit_datetime=%Y-%m-%d %H:%M:%S").unwrap();
1557 temp_file.flush().unwrap();
1558
1559 let content = std::fs::read_to_string(temp_file.path()).unwrap();
1561 let config = parse_ini_content(&content).unwrap();
1562
1563 let global_vars = GlobalVars::new();
1564 global_vars.config.set(config).unwrap();
1565 global_vars.set_obsidian_vars();
1566
1567 let root = global_vars.get_obsidian_root_path_dir();
1569 let commit = global_vars.get_obsidian_commit_path();
1570 let date = global_vars.get_template_commit_date_path();
1571 let datetime = global_vars.get_template_commit_datetime();
1572
1573 assert!(root.to_string_lossy().contains("test_obsidian"));
1574 assert!(commit.to_string_lossy().contains("TestCommits"));
1575 assert_eq!(date, "%Y-%m-%d.md");
1576 assert_eq!(datetime, "%Y-%m-%d %H:%M:%S");
1577 }
1578
1579 #[test]
1580 #[should_panic(expected = "Could not get")]
1581 fn test_get_obsidian_root_path_dir_not_set() {
1582 let global_vars = GlobalVars::new();
1583 global_vars.get_obsidian_root_path_dir();
1586 }
1587
1588 #[test]
1589 #[should_panic(expected = "Could not get")]
1590 fn test_get_obsidian_commit_path_not_set() {
1591 let global_vars = GlobalVars::new();
1592 global_vars.get_obsidian_commit_path();
1593 }
1594
1595 #[test]
1596 #[should_panic(expected = "Could not get")]
1597 fn test_get_template_commit_date_path_not_set() {
1598 let global_vars = GlobalVars::new();
1599 global_vars.get_template_commit_date_path();
1600 }
1601
1602 #[test]
1603 #[should_panic(expected = "Could not get")]
1604 fn test_get_template_commit_datetime_not_set() {
1605 let global_vars = GlobalVars::new();
1606 global_vars.get_template_commit_datetime();
1607 }
1608
1609 #[test]
1610 #[should_panic(expected = "Could not get Config")]
1611 fn test_get_config_not_initialized() {
1612 let global_vars = GlobalVars::new();
1613 global_vars.get_config();
1615 }
1616
1617 #[test]
1618 fn test_set_config_twice_fails() {
1619 let global_vars = GlobalVars::new();
1620 let config1 = Ini::new();
1621 let config2 = Ini::new();
1622
1623 assert!(global_vars.config.set(config1).is_ok());
1624 assert!(global_vars.config.set(config2).is_err());
1626 }
1627
1628 #[test]
1629 fn test_global_vars_set_all_end_to_end() {
1630 use std::io::Write;
1631 use tempfile::NamedTempFile;
1632
1633 let mut temp_file = NamedTempFile::new().unwrap();
1635 writeln!(temp_file, "[obsidian]").unwrap();
1636 writeln!(temp_file, "root_path_dir=/tmp/obsidian_test").unwrap();
1637 writeln!(temp_file, "commit_path=TestDiaries/TestCommits").unwrap();
1638 writeln!(temp_file, "[templates]").unwrap();
1639 writeln!(temp_file, "commit_date_path=%Y/%m-%B/%F.md").unwrap();
1640 writeln!(temp_file, "commit_datetime=%Y-%m-%d %H:%M:%S").unwrap();
1641 temp_file.flush().unwrap();
1642
1643 let content = std::fs::read_to_string(temp_file.path()).unwrap();
1645 let mut config = Ini::new();
1646 config.read(content).unwrap();
1647
1648 let global_vars = GlobalVars::new();
1650 let result = global_vars.config.set(config);
1651 assert!(result.is_ok());
1652
1653 global_vars.set_obsidian_vars();
1655
1656 let root = global_vars.get_obsidian_root_path_dir();
1658 let commit = global_vars.get_obsidian_commit_path();
1659 let date_path = global_vars.get_template_commit_date_path();
1660 let datetime = global_vars.get_template_commit_datetime();
1661
1662 assert!(root.to_string_lossy().contains("obsidian_test"));
1663 assert!(commit.to_string_lossy().contains("TestCommits"));
1664 assert_eq!(date_path, "%Y/%m-%B/%F.md");
1665 assert_eq!(datetime, "%Y-%m-%d %H:%M:%S");
1666 }
1667
1668 #[test]
1669 fn test_set_obsidian_root_path_dir_with_trailing_slash() {
1670 let mut config = Ini::new();
1671 config.set("obsidian", "root_path_dir", Some("/tmp/test/".to_string()));
1672 config.set(
1673 "templates",
1674 "commit_date_path",
1675 Some("%Y-%m-%d".to_string()),
1676 );
1677 config.set("templates", "commit_datetime", Some("%Y-%m-%d".to_string()));
1678
1679 let global_vars = GlobalVars::new();
1680 global_vars.config.set(config).unwrap();
1681 global_vars.set_obsidian_root_path_dir("obsidian");
1682
1683 let result = global_vars.get_obsidian_root_path_dir();
1684
1685 assert!(result.to_string_lossy().contains("test"));
1687 }
1688
1689 #[test]
1690 fn test_set_obsidian_commit_path_with_multiple_slashes() {
1691 let mut config = Ini::new();
1692 config.set(
1693 "obsidian",
1694 "commit_path",
1695 Some("Diaries//Commits///Nested".to_string()),
1696 );
1697 config.set(
1698 "templates",
1699 "commit_date_path",
1700 Some("%Y-%m-%d".to_string()),
1701 );
1702 config.set("templates", "commit_datetime", Some("%Y-%m-%d".to_string()));
1703
1704 let global_vars = GlobalVars::new();
1705 global_vars.config.set(config).unwrap();
1706 global_vars.set_obsidian_commit_path("obsidian");
1707
1708 let result = global_vars.get_obsidian_commit_path();
1709
1710 assert!(result.to_string_lossy().contains("Nested"));
1712 }
1713
1714 #[test]
1715 fn test_set_obsidian_root_path_dir_empty_string() {
1716 let mut config = Ini::new();
1717 config.set("obsidian", "root_path_dir", Some(String::new()));
1718 config.set(
1719 "templates",
1720 "commit_date_path",
1721 Some("%Y-%m-%d".to_string()),
1722 );
1723 config.set("templates", "commit_datetime", Some("%Y-%m-%d".to_string()));
1724
1725 let global_vars = GlobalVars::new();
1726 global_vars.config.set(config).unwrap();
1727 global_vars.set_obsidian_root_path_dir("obsidian");
1728
1729 let result = global_vars.get_obsidian_root_path_dir();
1730
1731 assert!(!result.to_string_lossy().is_empty());
1733 }
1734
1735 #[test]
1736 #[should_panic(expected = "Could not get commit_path from config")]
1737 fn test_set_obsidian_commit_path_missing_key() {
1738 let mut config = Ini::new();
1739 config.set("obsidian", "root_path_dir", Some("/tmp/test".to_string()));
1740 config.set(
1741 "templates",
1742 "commit_date_path",
1743 Some("%Y-%m-%d".to_string()),
1744 );
1745 config.set("templates", "commit_datetime", Some("%Y-%m-%d".to_string()));
1746
1747 let global_vars = GlobalVars::new();
1748 global_vars.config.set(config).unwrap();
1749
1750 global_vars.set_obsidian_commit_path("obsidian");
1751 }
1752
1753 #[test]
1754 #[should_panic(expected = "Could not get")]
1755 fn test_set_obsidian_root_path_dir_missing_key() {
1756 let mut config = Ini::new();
1757 config.set("obsidian", "commit_path", Some("commits".to_string()));
1758 config.set(
1759 "templates",
1760 "commit_date_path",
1761 Some("%Y-%m-%d".to_string()),
1762 );
1763 config.set("templates", "commit_datetime", Some("%Y-%m-%d".to_string()));
1764
1765 let global_vars = GlobalVars::new();
1766 global_vars.config.set(config).unwrap();
1767
1768 global_vars.set_obsidian_root_path_dir("obsidian");
1769 }
1770
1771 #[test]
1772 #[should_panic(expected = "Could not get the commit_date_path from INI")]
1773 fn test_set_templates_commit_date_path_missing_key() {
1774 let mut config = Ini::new();
1775 config.set("templates", "commit_datetime", Some("%Y-%m-%d".to_string()));
1776 config.set("obsidian", "root_path_dir", Some("/tmp".to_string()));
1777 config.set("obsidian", "commit_path", Some("commits".to_string()));
1778
1779 let global_vars = GlobalVars::new();
1780 global_vars.config.set(config).unwrap();
1781
1782 global_vars.set_templates_commit_date_path("templates");
1783 }
1784
1785 #[test]
1786 #[should_panic(expected = "Could not get the commit_datetime from INI")]
1787 fn test_set_templates_datetime_missing_key() {
1788 let mut config = Ini::new();
1789 config.set(
1790 "templates",
1791 "commit_date_path",
1792 Some("%Y-%m-%d".to_string()),
1793 );
1794 config.set("obsidian", "root_path_dir", Some("/tmp".to_string()));
1795 config.set("obsidian", "commit_path", Some("commits".to_string()));
1796
1797 let global_vars = GlobalVars::new();
1798 global_vars.config.set(config).unwrap();
1799
1800 global_vars.set_templates_datetime("templates");
1801 }
1802
1803 #[test]
1804 fn test_global_vars_set_all_method() {
1805 use std::io::Write;
1806 use tempfile::NamedTempFile;
1807
1808 let mut temp_file = NamedTempFile::new().unwrap();
1810 writeln!(temp_file, "[obsidian]").unwrap();
1811 writeln!(temp_file, "root_path_dir=/tmp/obsidian_full_test").unwrap();
1812 writeln!(temp_file, "commit_path=FullTest/Commits").unwrap();
1813 writeln!(temp_file, "[templates]").unwrap();
1814 writeln!(temp_file, "commit_date_path=%Y/%m/%d.md").unwrap();
1815 writeln!(temp_file, "commit_datetime=%Y-%m-%d %H:%M:%S").unwrap();
1816 temp_file.flush().unwrap();
1817
1818 let content = std::fs::read_to_string(temp_file.path()).unwrap();
1820 let config = parse_ini_content(&content).unwrap();
1821
1822 let global_vars = GlobalVars::new();
1824 global_vars.config.set(config).unwrap();
1825 global_vars.set_obsidian_vars();
1826
1827 let root = global_vars.get_obsidian_root_path_dir();
1829 let commit = global_vars.get_obsidian_commit_path();
1830 let date = global_vars.get_template_commit_date_path();
1831 let datetime = global_vars.get_template_commit_datetime();
1832
1833 assert!(root.to_string_lossy().contains("obsidian_full_test"));
1834 assert!(commit.to_string_lossy().contains("FullTest"));
1835 assert_eq!(date, "%Y/%m/%d.md");
1836 assert_eq!(datetime, "%Y-%m-%d %H:%M:%S");
1837 }
1838
1839 #[test]
1840 fn test_set_obsidian_vars_complete_workflow() {
1841 let mut config = Ini::new();
1842 config.set(
1843 "obsidian",
1844 "root_path_dir",
1845 Some("~/test/obsidian".to_string()),
1846 );
1847 config.set(
1848 "obsidian",
1849 "commit_path",
1850 Some("~/test/commits".to_string()),
1851 );
1852 config.set(
1853 "templates",
1854 "commit_date_path",
1855 Some("%Y/%m/%d.md".to_string()),
1856 );
1857 config.set(
1858 "templates",
1859 "commit_datetime",
1860 Some("%Y-%m-%d %H:%M:%S".to_string()),
1861 );
1862
1863 let global_vars = GlobalVars::new();
1864 global_vars.config.set(config).unwrap();
1865
1866 global_vars.set_obsidian_vars();
1868
1869 let root = global_vars.get_obsidian_root_path_dir();
1871 let commit = global_vars.get_obsidian_commit_path();
1872
1873 assert!(!root.to_string_lossy().contains('~'));
1875 assert!(!commit.to_string_lossy().contains('~'));
1876 assert!(root.to_string_lossy().contains("obsidian"));
1877 assert!(commit.to_string_lossy().contains("commits"));
1878 }
1879}
1880
1881#[cfg(test)]
1882#[cfg_attr(coverage_nightly, coverage(off))]
1883mod user_input_tests {
1884 use super::*;
1885 use clap::Parser;
1886
1887 #[test]
1888 fn test_user_input_parse_with_config() {
1889 let args = vec!["test_program", "--config-ini", "/path/to/config.ini"];
1890 let user_input = UserInput::try_parse_from(args).unwrap();
1891
1892 assert_eq!(
1893 user_input.config_ini,
1894 Some("/path/to/config.ini".to_string())
1895 );
1896 }
1897
1898 #[test]
1899 fn test_user_input_parse_without_config() {
1900 let args = vec!["test_program"];
1901 let user_input = UserInput::try_parse_from(args).unwrap();
1902
1903 assert_eq!(user_input.config_ini, None);
1904 }
1905
1906 #[test]
1907 fn test_user_input_parse_short_flag() {
1908 let args = vec!["test_program", "-c", "/short/path/config.ini"];
1909 let user_input = UserInput::try_parse_from(args).unwrap();
1910
1911 assert_eq!(
1912 user_input.config_ini,
1913 Some("/short/path/config.ini".to_string())
1914 );
1915 }
1916
1917 #[test]
1918 fn test_set_proper_home_dir_with_tilde() {
1919 let input = "~/test/path/file.ini";
1920 let result = set_proper_home_dir(input);
1921
1922 assert!(!result.contains('~'));
1924 assert!(result.ends_with("/test/path/file.ini"));
1925 }
1926
1927 #[test]
1928 fn test_set_proper_home_dir_without_tilde() {
1929 let input = "/absolute/path/file.ini";
1930 let result = set_proper_home_dir(input);
1931
1932 assert_eq!(result, input);
1934 }
1935
1936 #[test]
1937 fn test_set_proper_home_dir_multiple_tildes() {
1938 let input = "~/path/~/file.ini";
1939 let result = set_proper_home_dir(input);
1940
1941 assert!(!result.contains('~'));
1943 }
1944
1945 #[test]
1946 fn test_get_default_ini_path() {
1947 let result = get_default_ini_path();
1948
1949 assert!(result.ends_with(".config/rusty-commit-saver/rusty-commit-saver.ini"));
1951
1952 assert!(!result.contains('~'));
1954
1955 assert!(result.starts_with('/'));
1957 }
1958
1959 #[test]
1960 fn test_get_or_default_config_ini_path_with_config_and_tilde() {
1961 let args = vec!["test", "--config-ini", "~/my/config.ini"];
1963 let user_input = UserInput::try_parse_from(args).unwrap();
1964
1965 assert_eq!(user_input.config_ini, Some("~/my/config.ini".to_string()));
1968 }
1969
1970 #[test]
1971 fn test_get_or_default_config_ini_path_with_config_absolute_path() {
1972 let args = vec!["test", "--config-ini", "/absolute/path/config.ini"];
1974 let user_input = UserInput::try_parse_from(args).unwrap();
1975
1976 assert_eq!(
1977 user_input.config_ini,
1978 Some("/absolute/path/config.ini".to_string())
1979 );
1980 }
1981
1982 #[test]
1983 fn test_get_or_default_config_ini_path_without_config() {
1984 let args = vec!["test"];
1986 let user_input = UserInput::try_parse_from(args).unwrap();
1987
1988 assert_eq!(user_input.config_ini, None);
1990 }
1991
1992 #[test]
1993 fn test_parse_ini_content_valid() {
1994 let content = r"
1995[obsidian]
1996root_path_dir=~/Documents/Obsidian
1997commit_path=Diaries/Commits
1998
1999[templates]
2000commit_date_path=%Y/%m-%B/%F.md
2001commit_datetime=%Y-%m-%d
2002";
2003
2004 let result = parse_ini_content(content);
2005 assert!(result.is_ok());
2006
2007 let ini = result.unwrap();
2008 assert_eq!(
2009 ini.get("obsidian", "root_path_dir"),
2010 Some("~/Documents/Obsidian".to_string())
2011 );
2012 assert_eq!(
2013 ini.get("templates", "commit_date_path"),
2014 Some("%Y/%m-%B/%F.md".to_string())
2015 );
2016 }
2017
2018 #[test]
2019 fn test_parse_ini_content_invalid() {
2020 let content = "this is not valid ini format [[[";
2021
2022 let result = parse_ini_content(content);
2023 assert!(result.is_ok() || result.is_err());
2025 }
2026
2027 #[test]
2028 fn test_parse_ini_content_empty() {
2029 let content = "";
2030
2031 let result = parse_ini_content(content);
2032 assert!(result.is_ok());
2033
2034 let ini = result.unwrap();
2035 assert_eq!(ini.sections().len(), 0);
2036 }
2037
2038 #[test]
2039 fn test_retrieve_config_file_path_with_temp_file() {
2040 use std::io::Write;
2041 use tempfile::NamedTempFile;
2042
2043 let mut temp_file = NamedTempFile::new().unwrap();
2045 writeln!(temp_file, "[obsidian]").unwrap();
2046 writeln!(temp_file, "root_path_dir=/tmp/test").unwrap();
2047 writeln!(temp_file, "commit_path=commits").unwrap();
2048 writeln!(temp_file, "[templates]").unwrap();
2049 writeln!(temp_file, "commit_date_path=%Y-%m-%d.md").unwrap();
2050 writeln!(temp_file, "commit_datetime=%Y-%m-%d").unwrap();
2051 temp_file.flush().unwrap();
2052
2053 let path = temp_file.path().to_str().unwrap();
2056
2057 let content = std::fs::read_to_string(path).unwrap();
2060 let result = parse_ini_content(&content);
2061
2062 assert!(result.is_ok());
2063 let ini = result.unwrap();
2064 assert_eq!(
2065 ini.get("obsidian", "root_path_dir"),
2066 Some("/tmp/test".to_string())
2067 );
2068 }
2069
2070 #[test]
2071 fn test_ini_parsing_integration() {
2072 let content = r"
2073[obsidian]
2074root_path_dir=~/Documents/Obsidian
2075commit_path=Diaries/Commits
2076
2077[templates]
2078commit_date_path=%Y/%m-%B/%F.md
2079commit_datetime=%Y-%m-%d %H:%M:%S
2080";
2081
2082 let ini = parse_ini_content(content).unwrap();
2083
2084 assert!(ini.get("obsidian", "root_path_dir").is_some());
2086 assert!(ini.get("obsidian", "commit_path").is_some());
2087 assert!(ini.get("templates", "commit_date_path").is_some());
2088 assert!(ini.get("templates", "commit_datetime").is_some());
2089
2090 assert_eq!(ini.sections().len(), 2);
2092 }
2093
2094 #[test]
2108 fn test_line_606_explicit_coverage() {
2109 use std::panic;
2110
2111 let mut config = Ini::new();
2112 config.set("only_one_section", "key", Some("value".to_string()));
2113
2114 let global_vars = GlobalVars::new();
2115 global_vars.config.set(config).unwrap();
2116
2117 let result = panic::catch_unwind(|| global_vars.get_sections_from_config());
2118
2119 assert!(result.is_err(), "Should have panicked");
2120 }
2121
2122 #[test]
2123 fn test_set_all_loads_config_and_sets_vars() {
2124 use std::env;
2125 use std::fs;
2126 use tempfile::NamedTempFile;
2127
2128 let temp_file = NamedTempFile::new().expect("Failed to create temp file");
2129 let config_content = r"[obsidian]
2130root_path_dir = /tmp/test_obsidian
2131commit_path = Commits
2132
2133[templates]
2134commit_date_path = %Y/%m/%d.md
2135commit_datetime = %Y-%m-%d %H:%M:%S
2136";
2137 fs::write(temp_file.path(), config_content).expect("Failed to write temp config");
2138
2139 env::set_var(
2140 "RUSTY_COMMIT_SAVER_CONFIG",
2141 temp_file.path().to_str().unwrap(),
2142 );
2143
2144 let global_vars = GlobalVars::new();
2145 let result = global_vars.set_all();
2146
2147 assert!(std::ptr::eq(result, &raw const global_vars));
2149
2150 assert!(global_vars.config.get().is_some());
2152
2153 env::remove_var("RUSTY_COMMIT_SAVER_CONFIG");
2154 }
2155
2156 #[test]
2157 #[should_panic(expected = "config_path DOES NOT exists")]
2158 fn test_retrieve_config_file_path_panics_on_missing_file() {
2159 std::env::set_var("RUSTY_COMMIT_SAVER_CONFIG", "/nonexistent/path/config.ini");
2160 let _ = retrieve_config_file_path();
2161 }
2162
2163 #[test]
2164 fn test_get_or_default_config_ini_path_env_var_with_tilde() {
2165 use std::env;
2166
2167 let var_name = "RUSTY_COMMIT_SAVER_CONFIG";
2168 let original = env::var(var_name).ok();
2169
2170 env::set_var(var_name, "~/some/config/path.ini");
2171
2172 let result = get_or_default_config_ini_path();
2173
2174 match original {
2176 Some(val) => env::set_var(var_name, val),
2177 None => env::remove_var(var_name),
2178 }
2179
2180 assert!(!result.contains('~'), "Tilde should be expanded");
2182 assert!(result.ends_with("/some/config/path.ini"));
2183 }
2184
2185 #[test]
2186 fn test_resolve_config_path_cli_with_tilde() {
2187 let result = resolve_config_path(Some("~/my/config.ini".to_string()), None);
2188 assert!(!result.contains('~'));
2189 assert!(result.ends_with("/my/config.ini"));
2190 }
2191
2192 #[test]
2193 fn test_resolve_config_path_cli_without_tilde() {
2194 let result = resolve_config_path(Some("/absolute/path.ini".to_string()), None);
2195 assert_eq!(result, "/absolute/path.ini");
2196 }
2197
2198 #[test]
2199 fn test_resolve_config_path_default() {
2200 let result = resolve_config_path(None, None);
2201 assert!(result.contains("rusty-commit-saver.ini"));
2202 }
2203
2204 #[test]
2205 fn test_resolve_config_path_env_takes_precedence() {
2206 let result = resolve_config_path(
2207 Some("/cli/path.ini".to_string()),
2208 Some("/env/path.ini".to_string()),
2209 );
2210 assert_eq!(result, "/env/path.ini");
2211 }
2212
2213 #[test]
2214 fn test_get_or_default_config_ini_path_with_no_env_calls_cli_parser() {
2215 let parser_called = std::cell::Cell::new(false);
2216
2217 let result = get_or_default_config_ini_path_with(None, || {
2218 parser_called.set(true);
2219 Some("/mock/cli/path.ini".to_string())
2220 });
2221
2222 assert!(
2223 parser_called.get(),
2224 "CLI parser should be called when no env var"
2225 );
2226 assert_eq!(result, "/mock/cli/path.ini");
2227 }
2228
2229 #[test]
2230 fn test_get_or_default_config_ini_path_with_env_skips_cli_parser() {
2231 let parser_called = std::cell::Cell::new(false);
2232
2233 let result = get_or_default_config_ini_path_with(Some("/env/path.ini".to_string()), || {
2234 parser_called.set(true);
2235 Some("/should/not/be/used.ini".to_string())
2236 });
2237
2238 assert!(
2239 !parser_called.get(),
2240 "CLI parser should NOT be called when env var is set"
2241 );
2242 assert_eq!(result, "/env/path.ini");
2243 }
2244
2245 #[test]
2246 fn test_get_or_default_config_ini_path_with_cli_returns_default_when_none() {
2247 let result = get_or_default_config_ini_path_with(None, || None);
2248
2249 assert!(result.contains("rusty-commit-saver.ini"));
2251 }
2252
2253 #[test]
2254 fn test_get_or_default_config_ini_path_with_cli_tilde_expansion() {
2255 let result =
2256 get_or_default_config_ini_path_with(None, || Some("~/custom/config.ini".to_string()));
2257
2258 assert!(!result.contains('~'), "Tilde should be expanded");
2259 assert!(result.ends_with("/custom/config.ini"));
2260 }
2261
2262 #[test]
2263 fn test_parse_ini_content_find_invalid_case() {
2264 let cases = [
2265 "[unclosed",
2266 "no_section_key = value", "[section]\nweird line without equals",
2268 ];
2269
2270 for case in cases {
2271 let result = parse_ini_content(case);
2272 println!("{case:?} => {result:?}");
2273 }
2274 }
2275
2276 #[test]
2277 fn test_parse_ini_content_invalid_syntax() {
2278 let result = parse_ini_content("[unclosed");
2279
2280 assert!(result.is_err(), "Should fail on unclosed bracket");
2281 let err = result.unwrap_err();
2282 assert!(
2283 err.contains("Failed to parse INI"),
2284 "Error should contain expected prefix: {err}"
2285 );
2286 }
2287
2288 #[test]
2289 #[should_panic(expected = "Should have been able to read the file")]
2290 fn test_retrieve_config_file_path_panics_on_unreadable_file() {
2291 use std::fs::{self, File};
2292 use std::os::unix::fs::PermissionsExt;
2293 use tempfile::tempdir;
2294
2295 let dir = tempdir().unwrap();
2296 let file_path = dir.path().join("unreadable.ini");
2297
2298 File::create(&file_path).unwrap();
2300 fs::set_permissions(&file_path, fs::Permissions::from_mode(0o000)).unwrap();
2301
2302 std::env::set_var("RUSTY_COMMIT_SAVER_CONFIG", file_path.to_str().unwrap());
2303
2304 let _ = retrieve_config_file_path();
2306
2307 fs::set_permissions(&file_path, fs::Permissions::from_mode(0o644)).unwrap();
2309 }
2310}