345 lines
8.9 KiB
Rust
345 lines
8.9 KiB
Rust
use std::{
|
|
collections::HashMap,
|
|
fmt::{Display, Formatter},
|
|
};
|
|
|
|
use serde::Deserialize;
|
|
use terrors::OneOf;
|
|
|
|
use crate::filesystem::FileSystem;
|
|
|
|
#[derive(Debug, PartialEq, Eq, Deserialize)]
|
|
pub struct ServerConfig {
|
|
forge: HashMap<String, Forge>,
|
|
}
|
|
impl ServerConfig {
|
|
pub(crate) fn load(fs: &FileSystem) -> Result<Self, OneOf<(std::io::Error, toml::de::Error)>> {
|
|
let str = fs.read_file("git-next-server.toml").map_err(OneOf::new)?;
|
|
toml::from_str(&str).map_err(OneOf::new)
|
|
}
|
|
|
|
pub(crate) fn forges(&self) -> impl Iterator<Item = (ForgeName, &Forge)> {
|
|
self.forge
|
|
.iter()
|
|
.map(|(name, forge)| (ForgeName(name.clone()), forge))
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
|
|
pub struct RepoConfig {
|
|
branches: RepoBranches,
|
|
}
|
|
impl RepoConfig {
|
|
#[allow(dead_code)]
|
|
pub(crate) fn load(toml: &str) -> Result<Self, OneOf<(toml::de::Error,)>> {
|
|
toml::from_str(toml).map_err(OneOf::new)
|
|
}
|
|
|
|
pub(crate) const fn branches(&self) -> &RepoBranches {
|
|
&self.branches
|
|
}
|
|
}
|
|
impl Display for RepoConfig {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{:?}", self.branches)
|
|
}
|
|
}
|
|
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
|
|
pub struct RepoBranches {
|
|
main: String,
|
|
next: String,
|
|
dev: String,
|
|
}
|
|
impl RepoBranches {
|
|
pub fn main(&self) -> BranchName {
|
|
BranchName(self.main.clone())
|
|
}
|
|
|
|
pub fn next(&self) -> BranchName {
|
|
BranchName(self.next.clone())
|
|
}
|
|
|
|
pub fn dev(&self) -> BranchName {
|
|
BranchName(self.dev.clone())
|
|
}
|
|
}
|
|
impl Display for RepoBranches {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{:?}", self)
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
|
|
pub struct Forge {
|
|
forge_type: ForgeType,
|
|
hostname: String,
|
|
user: String,
|
|
token: String,
|
|
// API Token
|
|
// Private SSH Key Path
|
|
repos: HashMap<String, Repo>,
|
|
}
|
|
impl Forge {
|
|
#[allow(dead_code)]
|
|
pub const fn forge_type(&self) -> &ForgeType {
|
|
&self.forge_type
|
|
}
|
|
|
|
pub fn hostname(&self) -> Hostname {
|
|
Hostname(self.hostname.clone())
|
|
}
|
|
|
|
pub fn user(&self) -> User {
|
|
User(self.user.clone())
|
|
}
|
|
|
|
pub fn token(&self) -> ApiToken {
|
|
ApiToken(self.token.clone())
|
|
}
|
|
|
|
pub fn repos(&self) -> impl Iterator<Item = (RepoName, &Repo)> {
|
|
self.repos
|
|
.iter()
|
|
.map(|(name, repo)| (RepoName(name.clone()), repo))
|
|
}
|
|
}
|
|
impl Display for Forge {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{} - {}@{}", self.forge_type, self.user, self.hostname)
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
|
|
pub struct Repo {
|
|
repo: String,
|
|
branch: String,
|
|
}
|
|
impl Repo {
|
|
#[allow(dead_code)]
|
|
pub fn repo(&self) -> RepoPath {
|
|
RepoPath(self.repo.clone())
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub fn branch(&self) -> BranchName {
|
|
BranchName(self.branch.clone())
|
|
}
|
|
}
|
|
#[cfg(test)]
|
|
impl AsRef<Self> for Repo {
|
|
fn as_ref(&self) -> &Self {
|
|
self
|
|
}
|
|
}
|
|
impl Display for Repo {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{} - {}", self.repo, self.branch)
|
|
}
|
|
}
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct ForgeName(pub String);
|
|
impl Display for ForgeName {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{}", self.0)
|
|
}
|
|
}
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct Hostname(pub String);
|
|
impl Display for Hostname {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{}", self.0)
|
|
}
|
|
}
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct User(pub String);
|
|
impl Display for User {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{}", self.0)
|
|
}
|
|
}
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct ApiToken(pub String);
|
|
impl Display for ApiToken {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{}", self.0)
|
|
}
|
|
}
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct ForgeDetails {
|
|
pub name: ForgeName,
|
|
pub forge_type: ForgeType,
|
|
pub hostname: Hostname,
|
|
pub user: User,
|
|
pub token: ApiToken,
|
|
// API Token
|
|
// Private SSH Key Path
|
|
}
|
|
impl From<(&ForgeName, &Forge)> for ForgeDetails {
|
|
fn from(forge: (&ForgeName, &Forge)) -> Self {
|
|
Self {
|
|
name: forge.0.clone(),
|
|
forge_type: forge.1.forge_type.clone(),
|
|
hostname: forge.1.hostname(),
|
|
user: forge.1.user(),
|
|
token: forge.1.token(),
|
|
}
|
|
}
|
|
}
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct RepoName(pub String);
|
|
impl Display for RepoName {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{}", self.0)
|
|
}
|
|
}
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct RepoPath(pub String);
|
|
impl Display for RepoPath {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{}", self.0)
|
|
}
|
|
}
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct BranchName(pub String);
|
|
impl Display for BranchName {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{}", self.0)
|
|
}
|
|
}
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct RepoDetails {
|
|
pub name: RepoName,
|
|
pub repo: RepoPath,
|
|
pub branch: BranchName,
|
|
pub forge: ForgeDetails,
|
|
}
|
|
impl RepoDetails {
|
|
pub fn new(name: &RepoName, repo: &Repo, forge_name: &ForgeName, forge: &Forge) -> Self {
|
|
Self {
|
|
name: name.clone(),
|
|
repo: RepoPath(repo.repo.clone()),
|
|
branch: BranchName(repo.branch.clone()),
|
|
forge: ForgeDetails {
|
|
name: forge_name.clone(),
|
|
forge_type: forge.forge_type.clone(),
|
|
hostname: forge.hostname(),
|
|
user: forge.user(),
|
|
token: forge.token(),
|
|
},
|
|
}
|
|
}
|
|
}
|
|
impl Display for RepoDetails {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(
|
|
f,
|
|
"{}/{} ({}): {}:{}/{} @ {}",
|
|
self.forge.name,
|
|
self.name,
|
|
self.forge.forge_type,
|
|
self.forge.hostname,
|
|
self.forge.user,
|
|
self.repo,
|
|
self.branch,
|
|
)
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
|
|
pub enum ForgeType {
|
|
ForgeJo,
|
|
// Gitea,
|
|
// GitHub,
|
|
// GitLab,
|
|
// BitBucket,
|
|
}
|
|
impl Display for ForgeType {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{:?}", self)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
|
|
use crate::filesystem::FileSystem;
|
|
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_server_config_load() -> Result<(), OneOf<(std::io::Error, toml::de::Error)>> {
|
|
let fs = FileSystem::new_temp().map_err(OneOf::new)?;
|
|
fs.write_file(
|
|
"git-next-server.toml",
|
|
r#"
|
|
[forge.default]
|
|
forge_type = "ForgeJo"
|
|
hostname = "git.example.net"
|
|
user = "Bob"
|
|
token = "API-Token"
|
|
|
|
[forge.default.repos]
|
|
hello = { repo = "user/hello", branch = "main" }
|
|
world = { repo = "user/world", branch = "master" }
|
|
"#,
|
|
)
|
|
.map_err(OneOf::new)?;
|
|
let config = ServerConfig::load(&fs)?;
|
|
let expected = ServerConfig {
|
|
forge: HashMap::from([(
|
|
"default".to_string(),
|
|
Forge {
|
|
forge_type: ForgeType::ForgeJo,
|
|
hostname: "git.example.net".to_string(),
|
|
user: "Bob".to_string(),
|
|
token: "API-Token".to_string(),
|
|
repos: HashMap::from([
|
|
(
|
|
"hello".to_string(),
|
|
Repo {
|
|
repo: "user/hello".to_string(),
|
|
branch: "main".to_string(),
|
|
},
|
|
),
|
|
(
|
|
"world".to_string(),
|
|
Repo {
|
|
repo: "user/world".to_string(),
|
|
branch: "master".to_string(),
|
|
},
|
|
),
|
|
]),
|
|
},
|
|
)]),
|
|
};
|
|
assert_eq!(config, expected);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_repo_config_load() -> Result<(), OneOf<(toml::de::Error,)>> {
|
|
let toml = r#"
|
|
[branches]
|
|
main = "main"
|
|
next = "next"
|
|
dev = "dev"
|
|
|
|
[options]
|
|
"#;
|
|
let config = RepoConfig::load(toml)?;
|
|
|
|
assert_eq!(
|
|
config,
|
|
RepoConfig {
|
|
branches: RepoBranches {
|
|
main: "main".to_string(),
|
|
next: "next".to_string(),
|
|
dev: "dev".to_string(),
|
|
},
|
|
}
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
}
|