From f9daac2f402be285b6cbc5987cc5dfc0cf71ad83 Mon Sep 17 00:00:00 2001 From: PlexSheep Date: Thu, 25 Jan 2024 22:08:05 +0100 Subject: [PATCH] we can load a yaml config and have error handling for it --- .autocrate.yaml | 2 +- Cargo.toml | 1 + README.md | 6 +++--- src/config/cli.rs | 5 ----- src/config/mod.rs | 52 ++++++++++++++++++++++++++++++++++++----------- src/error.rs | 21 +++++++++++++++++++ src/lib.rs | 1 + src/main.rs | 4 +++- 8 files changed, 70 insertions(+), 22 deletions(-) create mode 100644 src/error.rs diff --git a/.autocrate.yaml b/.autocrate.yaml index eb8ea98..4d8fe0f 100644 --- a/.autocrate.yaml +++ b/.autocrate.yaml @@ -1,6 +1,6 @@ changelog: enable: true - git-log: true + git_log: true uses: cargo: diff --git a/Cargo.toml b/Cargo.toml index c281b4d..5495a59 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,7 @@ libpt = { version = "0.3.11", features = ["log"] } serde = { version = "1.0.195", features = ["derive"] } serde_yaml = "0.9.30" thiserror = "1.0.56" +url = { version = "2.5.0", features = ["serde"] } [[bin]] name = "autocrate" diff --git a/README.md b/README.md index 5ea9159..cf5223e 100644 --- a/README.md +++ b/README.md @@ -68,9 +68,9 @@ repository. It should contain the following parameters (replace the placeholders | Parent | Key | Value | Explanation | |-----------------|--------------|----------------------------------------------------------------------------------|------------------------------------------------------------------------------| -| (root) | `changelog` | list of keys with this as parent (`git-log` etc) | information on how a changelog is generated | +| (root) | `changelog` | list of keys with this as parent (`git_log` etc) | information on how a changelog is generated | | `changelog` | `enable` | `true`/`false` | If false, no changelog will be generated | -| `changelog` | `git-log` | `true`/`false` | should a changelog be generated with `git log`? | +| `changelog` | `git_log` | `true`/`false` | should a changelog be generated with `git log`? | | (root) | `uses` | list of keys with this as parent (`cargo` etc) | Marks features to be used by Autocrate | | `uses` | `cargo` | list of keys with this as parent (`publish` etc) | tells us that your project uses cargo | | `cargo` | `publish` | `true`/`false` | should we publish crates? | @@ -86,7 +86,7 @@ An example `.autocrate.yaml` could look like this: ```yaml changelog: enable: true - git-log: true + git_log: true uses: cargo: diff --git a/src/config/cli.rs b/src/config/cli.rs index 0a72775..9fff45f 100644 --- a/src/config/cli.rs +++ b/src/config/cli.rs @@ -1,8 +1,3 @@ -use serde; -use serde_yaml; - -use std::path::PathBuf; - use libpt::log::{Level, Logger}; use clap::Parser; diff --git a/src/config/mod.rs b/src/config/mod.rs index 3ae3922..3ebed02 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1,19 +1,20 @@ use std::{ - fmt::{write, Debug}, fs::File, path::PathBuf + collections::HashMap, fmt::Debug, fs::File, io::BufReader, path::PathBuf }; -use anyhow::{anyhow, Result}; use git2; use libpt::log::error; use serde::Deserialize; +use url::Url; -use self::cli::Cli; +use crate::error::*; pub mod cli; +use cli::Cli; #[derive(Debug, Clone, Deserialize)] pub struct Changelog { - enabled: bool, + enable: bool, git_log: bool, } @@ -28,17 +29,23 @@ pub struct Cargo { registries: Vec, } +#[derive(Debug, Clone, Deserialize)] +pub struct ApiAuth { user: String, pass: String } + #[derive(Debug, Clone, Deserialize)] pub struct Api { - api_type: ApiType, - publish: bool, - registries: Vec, + r#type: ApiType, + endpoint: Url, + auth: ApiAuth, } #[derive(Debug, Clone, Deserialize)] pub enum ApiType { + #[serde(alias="gitea")] Gitea, + #[serde(alias="gitlab")] Gitlab, + #[serde(alias="github", alias="GitHub")] Github, } @@ -46,7 +53,7 @@ pub enum ApiType { pub struct YamlConfig { pub changelog: Changelog, pub uses: Uses, - pub apis: Vec, + pub api: HashMap, } pub struct Config { @@ -73,14 +80,35 @@ impl Config { let repo = match git2::Repository::open_from_env() { Ok(repo) => repo, Err(err) => { - let msg = format!("could not find a git repository: {err:?}"); - error!("{}", msg); - return Err(anyhow!(msg)); + let err = Error::GitRepoNotFound; + error!("{err}"); + return Err(err); } }; let mut path = repo.path().to_path_buf(); path.pop(); // we want the real root, not the `.git` dir - todo!() + let yaml_file_name = if path.join(".autocrate.yaml").exists() { + ".autocrate.yaml" + } else if path.join(".autocrate.yml").exists() { + ".autocrate.yml" + } else { + let err = Error::NoYamlFile; + error!("{err}"); + return Err(err); + }; + let yaml_file_path = path.join(yaml_file_name); + // 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; + error!("{err}"); + return Err(err); + } + + let yaml_rd = BufReader::new(File::open(yaml_file_path)?); + let yaml: YamlConfig = serde_yaml::from_reader(yaml_rd)?; + + Ok(Config { yaml, repo, path }) } } diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..85754a3 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,21 @@ +use anyhow; +use thiserror::Error; + +pub type Result = std::result::Result; + +#[derive(Error, Debug)] +pub enum Error { + #[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) +} diff --git a/src/lib.rs b/src/lib.rs index ef68c36..5788bd5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1 +1,2 @@ +pub mod error; pub mod config; diff --git a/src/main.rs b/src/main.rs index 7e2beb5..bb60350 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,7 @@ use anyhow::Result; +use libpt::log::{debug, trace}; +mod error; mod config; use config::{cli::Cli, Config}; @@ -7,6 +9,6 @@ fn main() -> Result<()> { let cli = Cli::cli_parse(); let config = Config::load(cli.clone())?; - dbg!(config); + trace!("loaded config:\n{:#?}", config.yaml); todo!() }