gitcc_core/
config.rs

1//! Configuration
2
3use 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
13/// Config directory name
14pub const CONFIG_DIR_NAME: &str = ".gitcc";
15
16/// Config file name
17pub const CONFIG_FILE_NAME: &str = "config.toml";
18
19/// Configuration
20#[derive(Debug, Default, Deserialize, Serialize)]
21pub struct Config {
22    /// Commit configuration
23    pub commit: CommitConfig,
24    /// Versioning configuration
25    pub version: VersioningConfig,
26    /// Changelog configuration
27    pub changelog: ChangelogConfig,
28    /// Release configuration
29    pub release: ReleaseConfig,
30}
31
32impl Config {
33    /// Loads the configuration from a file system
34    ///
35    /// The configuration is looked into the parent git repo.
36    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    /// Saves the file to the file system
48    ///
49    /// The file is saved relative to the workdir of the parent git repo.
50    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                // do not overwrite
55                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    /// Returns the TOML representation of the configuration
71    pub fn to_toml(&self) -> Result<String, Error> {
72        Ok(toml::to_string(self)?)
73    }
74
75    /// Returns the YAML representation of the configuration
76    pub fn to_yaml(&self) -> Result<String, Error> {
77        Ok(serde_yaml::to_string(self)?)
78    }
79
80    /// Returns the path to the config file
81    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
91/// Returns the git root directory
92pub 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}