feat(config): User can specify git directory to use for a repo
Closes kemitix/git-next#53 Does not include using this information.
This commit is contained in:
parent
50a969ede6
commit
704853017b
4 changed files with 43 additions and 31 deletions
|
@ -62,6 +62,7 @@ tokio = { version = "1.37", features = ["full"] }
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
# Testing
|
# Testing
|
||||||
assert2 = "0.3"
|
assert2 = "0.3"
|
||||||
|
pretty_assertions = "1.4"
|
||||||
test-log = "0.2"
|
test-log = "0.2"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
|
|
||||||
|
|
|
@ -9,5 +9,5 @@ token = "API-Token"
|
||||||
# path to private SSH key for user?
|
# path to private SSH key for user?
|
||||||
|
|
||||||
[forge.default.repos]
|
[forge.default.repos]
|
||||||
hello = { repo = "user/hello", branch = "main" } # maps to https://git.example.net/user/hello on the branch 'main'
|
hello = { repo = "user/hello", branch = "main", gitdir = "/opt/git/projects/user/hello.git" } # maps to https://git.example.net/user/hello on the branch 'main'
|
||||||
world = { repo = "user/world", branch = "master" } # maps to the 'master' branch
|
world = { repo = "user/world", branch = "master", main = "master", next = "upcoming", "dev" = "develop" } # maps to the 'master' branch
|
||||||
|
|
|
@ -4,6 +4,7 @@ use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
fmt::{Display, Formatter},
|
fmt::{Display, Formatter},
|
||||||
ops::Deref,
|
ops::Deref,
|
||||||
|
path::PathBuf,
|
||||||
};
|
};
|
||||||
|
|
||||||
use secrecy::ExposeSecret;
|
use secrecy::ExposeSecret;
|
||||||
|
@ -16,7 +17,7 @@ use crate::filesystem::FileSystem;
|
||||||
#[derive(Debug, PartialEq, Eq, Deserialize)]
|
#[derive(Debug, PartialEq, Eq, Deserialize)]
|
||||||
pub struct ServerConfig {
|
pub struct ServerConfig {
|
||||||
webhook: Webhook,
|
webhook: Webhook,
|
||||||
forge: HashMap<String, Forge>,
|
forge: HashMap<String, ForgeConfig>,
|
||||||
}
|
}
|
||||||
impl ServerConfig {
|
impl ServerConfig {
|
||||||
pub(crate) fn load(fs: &FileSystem) -> Result<Self, OneOf<(std::io::Error, toml::de::Error)>> {
|
pub(crate) fn load(fs: &FileSystem) -> Result<Self, OneOf<(std::io::Error, toml::de::Error)>> {
|
||||||
|
@ -24,7 +25,7 @@ impl ServerConfig {
|
||||||
toml::from_str(&str).map_err(OneOf::new)
|
toml::from_str(&str).map_err(OneOf::new)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn forges(&self) -> impl Iterator<Item = (ForgeName, &Forge)> {
|
pub(crate) fn forges(&self) -> impl Iterator<Item = (ForgeName, &ForgeConfig)> {
|
||||||
self.forge
|
self.forge
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(name, forge)| (ForgeName(name.clone()), forge))
|
.map(|(name, forge)| (ForgeName(name.clone()), forge))
|
||||||
|
@ -119,16 +120,16 @@ impl Display for RepoBranches {
|
||||||
/// Defines a Forge to connect to
|
/// Defines a Forge to connect to
|
||||||
/// Maps from `git-next-server.toml` at `forge.{forge}`
|
/// Maps from `git-next-server.toml` at `forge.{forge}`
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
|
||||||
pub struct Forge {
|
pub struct ForgeConfig {
|
||||||
forge_type: ForgeType,
|
forge_type: ForgeType,
|
||||||
hostname: String,
|
hostname: String,
|
||||||
user: String,
|
user: String,
|
||||||
token: String,
|
token: String,
|
||||||
// API Token
|
// API Token
|
||||||
// Private SSH Key Path
|
// Private SSH Key Path
|
||||||
repos: HashMap<String, Repo>,
|
repos: HashMap<String, ServerRepoConfig>,
|
||||||
}
|
}
|
||||||
impl Forge {
|
impl ForgeConfig {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub const fn forge_type(&self) -> &ForgeType {
|
pub const fn forge_type(&self) -> &ForgeType {
|
||||||
&self.forge_type
|
&self.forge_type
|
||||||
|
@ -146,29 +147,30 @@ impl Forge {
|
||||||
ApiToken(self.token.clone().into())
|
ApiToken(self.token.clone().into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn repos(&self) -> impl Iterator<Item = (RepoAlias, &Repo)> {
|
pub fn repos(&self) -> impl Iterator<Item = (RepoAlias, &ServerRepoConfig)> {
|
||||||
self.repos
|
self.repos
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(name, repo)| (RepoAlias(name.clone()), repo))
|
.map(|(name, repo)| (RepoAlias(name.clone()), repo))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Display for Forge {
|
impl Display for ForgeConfig {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{} - {}@{}", self.forge_type, self.user, self.hostname)
|
write!(f, "{} - {}@{}", self.forge_type, self.user, self.hostname)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Defines a Repo within a Forge to be monitored by the server
|
/// Defines a Repo within a ForgeConfig to be monitored by the server
|
||||||
/// Maps from `git-next-server.toml` at `forge.{forge}.repos.{name}`
|
/// Maps from `git-next-server.toml` at `forge.{forge}.repos.{name}`
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
|
||||||
pub struct Repo {
|
pub struct ServerRepoConfig {
|
||||||
repo: String,
|
repo: String,
|
||||||
branch: String,
|
branch: String,
|
||||||
|
gitdir: Option<PathBuf>,
|
||||||
main: Option<String>,
|
main: Option<String>,
|
||||||
next: Option<String>,
|
next: Option<String>,
|
||||||
dev: Option<String>,
|
dev: Option<String>,
|
||||||
}
|
}
|
||||||
impl Repo {
|
impl ServerRepoConfig {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn repo(&self) -> RepoPath {
|
pub fn repo(&self) -> RepoPath {
|
||||||
RepoPath(self.repo.clone())
|
RepoPath(self.repo.clone())
|
||||||
|
@ -193,12 +195,12 @@ impl Repo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
impl AsRef<Self> for Repo {
|
impl AsRef<Self> for ServerRepoConfig {
|
||||||
fn as_ref(&self) -> &Self {
|
fn as_ref(&self) -> &Self {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Display for Repo {
|
impl Display for ServerRepoConfig {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{} - {}", self.repo, self.branch)
|
write!(f, "{} - {}", self.repo, self.branch)
|
||||||
}
|
}
|
||||||
|
@ -259,8 +261,8 @@ pub struct ForgeDetails {
|
||||||
// API Token
|
// API Token
|
||||||
// Private SSH Key Path
|
// Private SSH Key Path
|
||||||
}
|
}
|
||||||
impl From<(&ForgeName, &Forge)> for ForgeDetails {
|
impl From<(&ForgeName, &ForgeConfig)> for ForgeDetails {
|
||||||
fn from(forge: (&ForgeName, &Forge)) -> Self {
|
fn from(forge: (&ForgeName, &ForgeConfig)) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: forge.0.clone(),
|
name: forge.0.clone(),
|
||||||
forge_type: forge.1.forge_type.clone(),
|
forge_type: forge.1.forge_type.clone(),
|
||||||
|
@ -318,7 +320,12 @@ pub struct RepoDetails {
|
||||||
pub config: Option<RepoConfig>,
|
pub config: Option<RepoConfig>,
|
||||||
}
|
}
|
||||||
impl RepoDetails {
|
impl RepoDetails {
|
||||||
pub fn new(name: &RepoAlias, repo: &Repo, forge_name: &ForgeName, forge: &Forge) -> Self {
|
pub fn new(
|
||||||
|
name: &RepoAlias,
|
||||||
|
repo: &ServerRepoConfig,
|
||||||
|
forge_name: &ForgeName,
|
||||||
|
forge: &ForgeConfig,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
repo: RepoPath(repo.repo.clone()),
|
repo: RepoPath(repo.repo.clone()),
|
||||||
|
@ -372,13 +379,14 @@ impl Display for ForgeType {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
use crate::filesystem::FileSystem;
|
use crate::filesystem::FileSystem;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "forgejo")]
|
fn load_should_parse_server_config() -> Result<(), OneOf<(std::io::Error, toml::de::Error)>> {
|
||||||
fn test_server_config_load() -> Result<(), OneOf<(std::io::Error, toml::de::Error)>> {
|
|
||||||
let fs = FileSystem::new_temp().map_err(OneOf::new)?;
|
let fs = FileSystem::new_temp().map_err(OneOf::new)?;
|
||||||
fs.write_file(
|
fs.write_file(
|
||||||
"git-next-server.toml",
|
"git-next-server.toml",
|
||||||
|
@ -387,13 +395,13 @@ mod tests {
|
||||||
url = "http://localhost:9909/webhook"
|
url = "http://localhost:9909/webhook"
|
||||||
|
|
||||||
[forge.default]
|
[forge.default]
|
||||||
forge_type = "ForgeJo"
|
forge_type = "MockForge"
|
||||||
hostname = "git.example.net"
|
hostname = "git.example.net"
|
||||||
user = "Bob"
|
user = "Bob"
|
||||||
token = "API-Token"
|
token = "API-Token"
|
||||||
|
|
||||||
[forge.default.repos]
|
[forge.default.repos]
|
||||||
hello = { repo = "user/hello", branch = "main" }
|
hello = { repo = "user/hello", branch = "main", gitdir = "/opt/git/user/hello.git" }
|
||||||
world = { repo = "user/world", branch = "master", main = "main", next = "next", dev = "dev" }
|
world = { repo = "user/world", branch = "master", main = "main", next = "next", dev = "dev" }
|
||||||
|
|
||||||
[forge.default.repos.sam]
|
[forge.default.repos.sam]
|
||||||
|
@ -412,17 +420,18 @@ mod tests {
|
||||||
},
|
},
|
||||||
forge: HashMap::from([(
|
forge: HashMap::from([(
|
||||||
"default".to_string(),
|
"default".to_string(),
|
||||||
Forge {
|
ForgeConfig {
|
||||||
forge_type: ForgeType::ForgeJo,
|
forge_type: ForgeType::MockForge,
|
||||||
hostname: "git.example.net".to_string(),
|
hostname: "git.example.net".to_string(),
|
||||||
user: "Bob".to_string(),
|
user: "Bob".to_string(),
|
||||||
token: "API-Token".to_string(),
|
token: "API-Token".to_string(),
|
||||||
repos: HashMap::from([
|
repos: HashMap::from([
|
||||||
(
|
(
|
||||||
"hello".to_string(),
|
"hello".to_string(),
|
||||||
Repo {
|
ServerRepoConfig {
|
||||||
repo: "user/hello".to_string(),
|
repo: "user/hello".to_string(),
|
||||||
branch: "main".to_string(),
|
branch: "main".to_string(),
|
||||||
|
gitdir: Some("/opt/git/user/hello.git".into()),
|
||||||
main: None,
|
main: None,
|
||||||
next: None,
|
next: None,
|
||||||
dev: None,
|
dev: None,
|
||||||
|
@ -430,9 +439,10 @@ mod tests {
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"world".to_string(),
|
"world".to_string(),
|
||||||
Repo {
|
ServerRepoConfig {
|
||||||
repo: "user/world".to_string(),
|
repo: "user/world".to_string(),
|
||||||
branch: "master".to_string(),
|
branch: "master".to_string(),
|
||||||
|
gitdir: None,
|
||||||
main: Some("main".to_string()),
|
main: Some("main".to_string()),
|
||||||
next: Some("next".to_string()),
|
next: Some("next".to_string()),
|
||||||
dev: Some("dev".to_string()),
|
dev: Some("dev".to_string()),
|
||||||
|
@ -440,9 +450,10 @@ mod tests {
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"sam".to_string(),
|
"sam".to_string(),
|
||||||
Repo {
|
ServerRepoConfig {
|
||||||
repo: "user/sam".to_string(),
|
repo: "user/sam".to_string(),
|
||||||
branch: "main".to_string(),
|
branch: "main".to_string(),
|
||||||
|
gitdir: None,
|
||||||
main: Some("master".to_string()),
|
main: Some("master".to_string()),
|
||||||
next: Some("upcoming".to_string()),
|
next: Some("upcoming".to_string()),
|
||||||
dev: Some("sam-dev".to_string()),
|
dev: Some("sam-dev".to_string()),
|
||||||
|
|
|
@ -15,11 +15,11 @@ use crate::{
|
||||||
filesystem::FileSystem,
|
filesystem::FileSystem,
|
||||||
server::{
|
server::{
|
||||||
actors::webhook,
|
actors::webhook,
|
||||||
config::{Forge, ForgeName, RepoAlias, Webhook},
|
config::{ForgeConfig, ForgeName, RepoAlias, Webhook},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::{actors::repo::RepoActor, config::Repo};
|
use self::{actors::repo::RepoActor, config::ServerRepoConfig};
|
||||||
|
|
||||||
pub fn init(fs: FileSystem) {
|
pub fn init(fs: FileSystem) {
|
||||||
let file_name = "git-next-server.toml";
|
let file_name = "git-next-server.toml";
|
||||||
|
@ -68,7 +68,7 @@ pub async fn start(fs: FileSystem, net: Network) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_forge_repos(
|
fn create_forge_repos(
|
||||||
forge: &Forge,
|
forge: &ForgeConfig,
|
||||||
forge_name: ForgeName,
|
forge_name: ForgeName,
|
||||||
webhook: &Webhook,
|
webhook: &Webhook,
|
||||||
net: &Network,
|
net: &Network,
|
||||||
|
@ -85,10 +85,10 @@ fn create_forge_repos(
|
||||||
|
|
||||||
fn create_actor(
|
fn create_actor(
|
||||||
forge_name: ForgeName,
|
forge_name: ForgeName,
|
||||||
forge: config::Forge,
|
forge: config::ForgeConfig,
|
||||||
webhook: &Webhook,
|
webhook: &Webhook,
|
||||||
net: &Network,
|
net: &Network,
|
||||||
) -> impl Fn((RepoAlias, &Repo)) -> (ForgeName, RepoAlias, RepoActor) {
|
) -> impl Fn((RepoAlias, &ServerRepoConfig)) -> (ForgeName, RepoAlias, RepoActor) {
|
||||||
let webhook = webhook.clone();
|
let webhook = webhook.clone();
|
||||||
let net = net.clone();
|
let net = net.clone();
|
||||||
move |(repo_name, repo)| {
|
move |(repo_name, repo)| {
|
||||||
|
|
Loading…
Reference in a new issue