diff --git a/src/config/mod.rs b/src/config/mod.rs index 3ebed02..9adce03 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1,9 +1,7 @@ -use std::{ - collections::HashMap, fmt::Debug, fs::File, io::BufReader, path::PathBuf -}; +use std::{collections::HashMap, fmt::Debug, fs::File, io::BufReader, path::PathBuf}; use git2; -use libpt::log::error; +use libpt::log::{debug, error, trace}; use serde::Deserialize; use url::Url; @@ -30,22 +28,47 @@ pub struct Cargo { } #[derive(Debug, Clone, Deserialize)] -pub struct ApiAuth { user: String, pass: String } +pub struct ApiAuth { + user: String, + pass: Option, + pass_file: Option, +} + +impl ApiAuth { + pub fn check(&self) -> Result<()> { + if self.pass.is_some() && self.pass_file.is_some() { + let err = ConfigError::YamlApiAuthBothPass(self.clone()).into(); + error!("{err}"); + return Err(err); + } + Ok(()) + } +} #[derive(Debug, Clone, Deserialize)] pub struct Api { r#type: ApiType, endpoint: Url, - auth: ApiAuth, + /// May be left empty if the Api does not need auth or the auth is part of the + /// [endpoint](Api::endpoint) [Url]. + auth: Option, +} +impl Api { + pub fn check(&self) -> Result<()> { + if let Some(auth) = &self.auth { + auth.check()?; + } + Ok(()) + } } #[derive(Debug, Clone, Deserialize)] pub enum ApiType { - #[serde(alias="gitea")] + #[serde(alias = "gitea")] Gitea, - #[serde(alias="gitlab")] + #[serde(alias = "gitlab")] Gitlab, - #[serde(alias="github", alias="GitHub")] + #[serde(alias = "github", alias = "GitHub")] Github, } @@ -53,7 +76,17 @@ pub enum ApiType { pub struct YamlConfig { pub changelog: Changelog, pub uses: Uses, - pub api: HashMap, + pub api: HashMap, +} + +impl YamlConfig { + /// check if the built configuration is valid + pub fn check(&self) -> Result<()> { + for api in &self.api { + api.1.check()?; + } + Ok(()) + } } pub struct Config { @@ -80,7 +113,7 @@ impl Config { let repo = match git2::Repository::open_from_env() { Ok(repo) => repo, Err(err) => { - let err = Error::GitRepoNotFound; + let err = ConfigError::GitRepoNotFound.into(); error!("{err}"); return Err(err); } @@ -93,7 +126,7 @@ impl Config { } else if path.join(".autocrate.yml").exists() { ".autocrate.yml" } else { - let err = Error::NoYamlFile; + let err = ConfigError::NoYamlFile.into(); error!("{err}"); return Err(err); }; @@ -101,13 +134,17 @@ impl Config { // we can be sure it exists from the checks above assert!(yaml_file_path.exists()); if !yaml_file_path.is_file() { - let err = Error::YamlFileIsNotFile; + let err = ConfigError::YamlFileIsNotFile.into(); error!("{err}"); return Err(err); } let yaml_rd = BufReader::new(File::open(yaml_file_path)?); + debug!("reading yaml config and building data structure"); let yaml: YamlConfig = serde_yaml::from_reader(yaml_rd)?; + trace!("load config:\n{:#?}", yaml); + yaml.check()?; + debug!("built and checked yaml config"); Ok(Config { yaml, repo, path }) } diff --git a/src/error.rs b/src/error.rs index 85754a3..01b172b 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,21 +1,31 @@ use anyhow; use thiserror::Error; +use crate::config::ApiAuth; + pub type Result = std::result::Result; #[derive(Error, Debug)] pub enum Error { + /// Bad IO operation + #[error("Bad IO operation")] + IO(#[from] std::io::Error), + #[error("Bad configuration file")] + Config(#[from] ConfigError), + #[error(transparent)] + Other(#[from] anyhow::Error), + #[error("Yaml error")] + SerdeYaml(#[from] serde_yaml::Error), +} + +#[derive(Error, Debug)] +pub enum ConfigError { + #[error("could not find git repository")] + GitRepoNotFound, #[error("no \".autocrate.yaml\" or \".autocrate.yml\" found in repository root")] NoYamlFile, #[error("the autocrate config file is not a regular file (is it a directory?)")] YamlFileIsNotFile, - #[error("could not find git repository")] - GitRepoNotFound, - /// Bad IO operation - #[error("Bad IO operation")] - IO(#[from] std::io::Error), - #[error(transparent)] - Other(#[from] anyhow::Error), - #[error("Yaml error")] - SerdeYaml(#[from] serde_yaml::Error) + #[error("api {0:?} provides both a `pass` and a `pass_file`")] + YamlApiAuthBothPass(ApiAuth), } diff --git a/src/main.rs b/src/main.rs index bb60350..4f88ed6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,5 @@ fn main() -> Result<()> { let cli = Cli::cli_parse(); let config = Config::load(cli.clone())?; - trace!("loaded config:\n{:#?}", config.yaml); todo!() }