From e9685abf5fc29fe2bee0fd7140f72e2264fc8bd0 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Mon, 8 Apr 2024 08:05:13 +0100 Subject: [PATCH] feat(config): Repos specify which branch to read config from --- server-default.toml | 3 +- src/server/actors/repo.rs | 2 +- src/server/config.rs | 125 +++++++++++++++++++++++++++++++------- src/server/mod.rs | 18 ++---- 4 files changed, 112 insertions(+), 36 deletions(-) diff --git a/server-default.toml b/server-default.toml index a75ae3ee..0c833a22 100644 --- a/server-default.toml +++ b/server-default.toml @@ -6,4 +6,5 @@ user = "git-next" # the user to perform actions as # path to private SSH key for user? [forge.default.repos] -hello = "user/hello" # maps to https://git.example.net/user/hello and git@git.example.net:user/hello.git +hello = { repo = "user/hello", branch = "main" } # maps to https://git.example.net/user/hello on the branch 'main' +world = { repo = "user/world", branch = "master" } # maps to the 'master' branch diff --git a/src/server/actors/repo.rs b/src/server/actors/repo.rs index 6d8d7d62..00ba7e08 100644 --- a/src/server/actors/repo.rs +++ b/src/server/actors/repo.rs @@ -17,7 +17,7 @@ impl Handler for RepoActor { fn handle(&mut self, _msg: StartRepo, _ctx: &mut Self::Context) -> Self::Result { info!( "Starting Repo: {} - {}", - self.details.name.0, self.details.path.0 + self.details.name.0, self.details.repo.0 ); } } diff --git a/src/server/config.rs b/src/server/config.rs index 9e9c468e..018657d3 100644 --- a/src/server/config.rs +++ b/src/server/config.rs @@ -11,6 +11,18 @@ use crate::filesystem::FileSystem; pub struct Config { forge: HashMap, } +impl Config { + pub(crate) fn load(fs: &FileSystem) -> Result> { + 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 { + self.forge + .iter() + .map(|(name, forge)| (ForgeName(name.clone()), forge)) + } +} #[derive(Debug, PartialEq, Eq, Deserialize)] pub struct Forge { @@ -19,26 +31,62 @@ pub struct Forge { user: String, // API Token // Private SSH Key Path - repos: HashMap, + repos: HashMap, } impl Forge { pub const fn forge_type(&self) -> &ForgeType { &self.forge_type } - pub fn hostname(&self) -> &str { - &self.hostname + pub fn hostname(&self) -> Hostname { + Hostname(self.hostname.clone()) } - pub fn user(&self) -> &str { - &self.user + pub fn user(&self) -> User { + User(self.user.clone()) } - pub fn repos(&self) -> impl Iterator { - self.repos.iter() + pub fn repos(&self) -> impl Iterator { + self.repos + .iter() + .map(|(name, repo)| (RepoName(name.clone()), repo)) } } +#[derive(Debug, PartialEq, Eq, Deserialize)] +pub struct Repo { + repo: String, + branch: String, +} +impl Repo { + #[cfg(test)] + pub fn new(repo: &str, branch: &str) -> Self { + Self { + repo: repo.to_string(), + branch: branch.to_string(), + } + } + #[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 for Repo { + fn as_ref(&self) -> &Repo { + self + } +} +impl Display for Repo { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{} - {}", self.repo, self.branch) + } +} #[derive(Clone)] pub struct ForgeName(pub String); impl Display for ForgeName { @@ -47,7 +95,17 @@ impl Display for ForgeName { } } pub struct Hostname(pub String); +impl Display for Hostname { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} pub struct User(pub String); +impl Display for User { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} pub struct ForgeDetails { pub name: ForgeName, pub forge_type: ForgeType, @@ -74,11 +132,38 @@ impl Display for RepoName { } } pub struct RepoPath(pub String); +impl Display for RepoPath { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} +pub struct BranchName(pub String); +impl Display for BranchName { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} pub struct RepoDetails { pub name: RepoName, - pub path: RepoPath, + 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: Hostname(forge.hostname.clone()), + user: User(forge.user.clone()), + }, + } + } +} #[derive(Clone, Debug, PartialEq, Eq, Deserialize)] pub enum ForgeType { @@ -94,18 +179,6 @@ impl Display for ForgeType { } } -#[allow(dead_code)] -impl Config { - pub(crate) fn load(fs: &FileSystem) -> Result> { - 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 { - self.forge.iter() - } -} - #[cfg(test)] mod tests { use assert2::let_assert; @@ -126,7 +199,8 @@ mod tests { user = "Bob" [forge.default.repos] - hello = "user/world" + hello = { repo = "user/hello", branch = "main" } + world = { repo = "user/world", branch = "master" } "#, ) .map_err(OneOf::new)?; @@ -135,7 +209,14 @@ mod tests { assert_eq!(default.forge_type, ForgeType::ForgeJo); assert_eq!(default.hostname, "git.example.net".to_string()); assert_eq!(default.user, "Bob".to_string()); - assert_eq!(default.repos.get("hello"), Some(&"user/world".to_string())); + assert_eq!( + default.repos.get("hello"), + Some(Repo::new("user/hello", "main").as_ref()) + ); + assert_eq!( + default.repos.get("world"), + Some(Repo::new("user/world", "master").as_ref()) + ); Ok(()) } diff --git a/src/server/mod.rs b/src/server/mod.rs index ef4e2085..120989ee 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -47,27 +47,21 @@ pub fn start(fs: FileSystem) { info!("Loaded config"); let mut actors: Vec<(ForgeName, RepoName, actors::repo::RepoActor)> = vec![]; config.forges().for_each(|(forge_name, forge)| { - let forge_name = ForgeName(forge_name.clone()); let span = tracing::info_span!("Forge", %forge_name); let _guard = span.enter(); info!("Forge: {}", forge_name); info!("Forge Type: {}", forge.forge_type()); info!("Hostname: {}", forge.hostname()); info!("User: {}", forge.user()); - forge.repos().for_each(|(repo_name, path)| { - let repo_name = RepoName(repo_name.clone()); - let span = tracing::info_span!("Repo", %repo_name); + forge.repos().for_each(|(repo_name, repo)| { + let span = tracing::info_span!("Repo", %repo_name, %repo); let _guard = span.enter(); - info!("Repo: {} - {}", repo_name, path); + info!("Creating Repo"); let actor = actors::repo::RepoActor { - details: config::RepoDetails { - name: repo_name.clone(), - path: config::RepoPath(path.clone()), - forge: (&forge_name, forge).into(), - }, + details: config::RepoDetails::new(&repo_name, repo, &forge_name, forge), }; - actors.push((forge_name.clone(), repo_name.clone(), actor)); - info!("Created actor for repo: {} - {}", repo_name, path); + actors.push((forge_name.clone(), repo_name, actor)); + info!("Created Repo"); }); }); info!("Sending StartRepo to all actors...");