1use std::{
4 fs,
5 path::{Path, PathBuf},
6};
7
8use gitcc_git::discover_repo;
9use serde::{Deserialize, Serialize};
10
11use crate::{error::Error, ChangelogConfig, CommitConfig, ReleaseConfig, VersioningConfig};
12
13pub const CONFIG_DIR_NAME: &str = ".gitcc";
15
16pub const CONFIG_FILE_NAME: &str = "config.toml";
18
19#[derive(Debug, Default, Deserialize, Serialize)]
21pub struct Config {
22 pub commit: CommitConfig,
24 pub version: VersioningConfig,
26 pub changelog: ChangelogConfig,
28 pub release: ReleaseConfig,
30}
31
32impl Config {
33 pub fn load_from_fs(cwd: &Path) -> Result<Option<Self>, Error> {
37 let cfg_file = Self::file_path(cwd)?;
38 if cfg_file.exists() && cfg_file.is_file() {
39 let data = fs::read_to_string(&cfg_file)?;
40 let config = toml::from_str::<Self>(&data)?;
41 Ok(Some(config))
42 } else {
43 Ok(None)
44 }
45 }
46
47 pub fn save_to_fs(&self, cwd: &Path, overwrite: bool) -> Result<(), Error> {
51 let cfg_file = Self::file_path(cwd)?;
52 if cfg_file.exists() {
53 if !overwrite {
54 return Err(Error::msg("config file already exists"));
56 }
57 fs::remove_file(&cfg_file)?;
58 }
59
60 let cfg_dir = cfg_file.parent().unwrap();
61 if !cfg_dir.exists() {
62 fs::create_dir(cfg_dir)?;
63 }
64 let cfg_str = toml::to_string(self)?;
65 fs::write(cfg_dir.join(CONFIG_FILE_NAME), cfg_str)?;
66
67 Ok(())
68 }
69
70 pub fn to_toml(&self) -> Result<String, Error> {
72 Ok(toml::to_string(self)?)
73 }
74
75 pub fn to_yaml(&self) -> Result<String, Error> {
77 Ok(serde_yaml::to_string(self)?)
78 }
79
80 fn file_path(cwd: &Path) -> Result<PathBuf, Error> {
82 let repo = discover_repo(cwd)?;
83 let repo_dir = repo
84 .workdir()
85 .ok_or(Error::msg("git repo workdir not found (bare repo)"))?;
86 let cfg_file = repo_dir.join(CONFIG_DIR_NAME).join(CONFIG_FILE_NAME);
87 Ok(cfg_file)
88 }
89}
90
91pub fn get_root_dir(cwd: &Path) -> Option<PathBuf> {
93 match discover_repo(cwd) {
94 Ok(repo) => repo.workdir().map(|p| p.to_owned()),
95 Err(_) => None,
96 }
97}