feat: add config
All checks were successful
continuous-integration/drone/push Build is passing

Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
Kasper Juul Hermansen 2024-09-12 20:14:44 +02:00
parent e7b4c8e819
commit b46ddb2d6a
Signed by: kjuulh
GPG Key ID: D85D7535F18F35FA
4 changed files with 292 additions and 1 deletions

87
Cargo.lock generated
View File

@ -72,6 +72,17 @@ version = "1.0.88"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e1496f8fb1fbf272686b8d37f523dab3e4a7443300055e74cdaa449f3114356"
[[package]]
name = "async-trait"
version = "0.1.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "autocfg"
version = "1.3.0"
@ -163,6 +174,12 @@ version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "getrandom"
version = "0.2.15"
@ -185,15 +202,23 @@ name = "gitnow"
version = "0.1.0"
dependencies = [
"anyhow",
"async-trait",
"clap",
"dotenv",
"serde",
"tokio",
"toml",
"tracing",
"tracing-subscriber",
"uuid",
]
[[package]]
name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
[[package]]
name = "heck"
version = "0.5.0"
@ -206,6 +231,16 @@ version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "indexmap"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
dependencies = [
"equivalent",
"hashbrown",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
@ -386,6 +421,15 @@ dependencies = [
"syn",
]
[[package]]
name = "serde_spanned"
version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d"
dependencies = [
"serde",
]
[[package]]
name = "sharded-slab"
version = "0.1.7"
@ -476,6 +520,40 @@ dependencies = [
"syn",
]
[[package]]
name = "toml"
version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit",
]
[[package]]
name = "toml_datetime"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.22.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"winnow",
]
[[package]]
name = "tracing"
version = "0.1.40"
@ -661,3 +739,12 @@ name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winnow"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f"
dependencies = [
"memchr",
]

View File

@ -14,3 +14,5 @@ dotenv.workspace = true
serde = { version = "1.0.197", features = ["derive"] }
uuid = { version = "1.7.0", features = ["v4"] }
async-trait = "0.1.82"
toml = "0.8.19"

View File

@ -1,5 +1,6 @@
use anyhow::Context;
use clap::{Parser, Subcommand};
use commands::root::RootCommand;
#[derive(Parser)]
#[command(author, version, about, long_about = Some("Navigate git projects at the speed of thought"))]
@ -17,14 +18,208 @@ enum Commands {
async fn main() -> anyhow::Result<()> {
dotenv::dotenv().ok();
tracing_subscriber::fmt::init();
let app = app::App::new_static();
let cli = Command::parse();
tracing::debug!("Starting cli");
match cli.command {
Some(_) => todo!(),
None => todo!(),
None => {
RootCommand::new(app).execute().await?;
}
}
Ok(())
}
mod config {
use std::path::Path;
use anyhow::Context;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct Config {
#[serde(default)]
pub providers: Providers,
}
#[derive(Debug, Default, Serialize, Deserialize, PartialEq)]
pub struct Providers {
#[serde(default)]
pub github: Vec<GitHub>,
#[serde(default)]
pub gitea: Vec<Gitea>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct GitHub {
#[serde(default)]
pub users: Vec<GitHubUser>,
#[serde(default)]
pub organisations: Vec<GitHubOrganisation>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct GitHubUser(String);
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct GitHubOrganisation(String);
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct Gitea {
#[serde(default)]
pub users: Vec<GiteaUser>,
#[serde(default)]
pub organisations: Vec<GiteaOrganisation>,
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct GiteaUser(String);
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct GiteaOrganisation(String);
impl Config {
pub async fn from_file(file_path: &Path) -> anyhow::Result<Config> {
let file_content = tokio::fs::read_to_string(file_path).await?;
Self::from_string(&file_content)
}
pub fn from_string(content: &str) -> anyhow::Result<Config> {
toml::from_str(content).context("failed to deserialize config file")
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_can_parse_config() -> anyhow::Result<()> {
let content = r#"
[[providers.github]]
users = ["kjuulh"]
organisations = ["lunarway"]
[[providers.github]]
users = ["other"]
organisations = ["org"]
[[providers.gitea]]
users = ["kjuulh"]
organisations = ["lunarway"]
[[providers.gitea]]
users = ["other"]
organisations = ["org"]
[[providers.gitea]]
"#;
let config = Config::from_string(content)?;
assert_eq!(
Config {
providers: Providers {
github: vec![
GitHub {
users: vec![GitHubUser("kjuulh".into())],
organisations: vec![GitHubOrganisation("lunarway".into())]
},
GitHub {
users: vec![GitHubUser("other".into())],
organisations: vec![GitHubOrganisation("org".into())]
}
],
gitea: vec![
Gitea {
users: vec![GiteaUser("kjuulh".into())],
organisations: vec![GiteaOrganisation("lunarway".into())]
},
Gitea {
users: vec![GiteaUser("other".into())],
organisations: vec![GiteaOrganisation("org".into())]
},
Gitea {
users: vec![],
organisations: vec![]
},
]
}
},
config
);
Ok(())
}
#[test]
fn test_can_parse_empty_config() -> anyhow::Result<()> {
let content = r#"
# empty file
"#;
let config = Config::from_string(content)?;
assert_eq!(
Config {
providers: Providers {
github: vec![],
gitea: vec![]
}
},
config
);
Ok(())
}
}
}
mod git_provider {
use async_trait::async_trait;
pub struct Repository {}
#[async_trait]
pub trait GitProvider {
async fn list_repositories(&self) -> anyhow::Result<Vec<Repository>>;
}
}
mod app {
#[derive(Debug)]
pub struct App {}
impl App {
pub fn new_static() -> &'static App {
Box::leak(Box::new(App {}))
}
}
}
mod commands {
pub mod root {
use crate::app::App;
#[derive(Debug, Clone)]
pub struct RootCommand {
app: &'static App,
}
impl RootCommand {
pub fn new(app: &'static App) -> Self {
Self { app }
}
#[tracing::instrument]
pub async fn execute(&mut self) -> anyhow::Result<()> {
tracing::debug!("executing");
Ok(())
}
}
}
}

View File

@ -0,0 +1,7 @@
[[providers.github]]
users = ["kjuulh"]
organisations = ["lunarway"]
[[providers.gitea]]
users = ["kjuulh"]
organisation = ["noorgplease"]