forked from kemitix/git-next
feat: Abstract Git command execution into injectable enum
Closes kemitix/git-next#36
This commit is contained in:
parent
fb74879309
commit
5fcf16ea75
9 changed files with 229 additions and 97 deletions
|
@ -4,6 +4,8 @@ mod server;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use kxio::{filesystem, network::Network};
|
use kxio::{filesystem, network::Network};
|
||||||
|
|
||||||
|
use crate::server::git::Git;
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[clap(version = clap::crate_version!(), author = clap::crate_authors!(), about = clap::crate_description!())]
|
#[clap(version = clap::crate_version!(), author = clap::crate_authors!(), about = clap::crate_description!())]
|
||||||
struct Commands {
|
struct Commands {
|
||||||
|
@ -26,6 +28,7 @@ enum Server {
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let fs = filesystem::FileSystem::new_real(None);
|
let fs = filesystem::FileSystem::new_real(None);
|
||||||
let net = Network::new_real();
|
let net = Network::new_real();
|
||||||
|
let git = Git::new_real();
|
||||||
let commands = Commands::parse();
|
let commands = Commands::parse();
|
||||||
|
|
||||||
match commands.command {
|
match commands.command {
|
||||||
|
@ -37,7 +40,7 @@ async fn main() {
|
||||||
server::init(fs);
|
server::init(fs);
|
||||||
}
|
}
|
||||||
Server::Start => {
|
Server::Start => {
|
||||||
server::start(fs, net).await;
|
server::start(fs, net, git).await;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,9 @@
|
||||||
use std::fmt::Display;
|
|
||||||
|
|
||||||
use actix::prelude::*;
|
use actix::prelude::*;
|
||||||
|
|
||||||
use kxio::network;
|
use kxio::network;
|
||||||
use secrecy::ExposeSecret;
|
|
||||||
use tracing::{error, info, warn};
|
use tracing::{error, info, warn};
|
||||||
|
|
||||||
use crate::server::{
|
use crate::server::{actors::repo::ValidateRepo, config, forge, git::Git, types::ResetForce};
|
||||||
actors::repo::{branch, ValidateRepo},
|
|
||||||
config::{self, BranchName},
|
|
||||||
forge,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{RepoActor, StartMonitoring};
|
use super::{RepoActor, StartMonitoring};
|
||||||
|
|
||||||
|
@ -19,6 +12,7 @@ pub async fn validate_positions(
|
||||||
repo_details: config::RepoDetails,
|
repo_details: config::RepoDetails,
|
||||||
config: config::RepoConfig,
|
config: config::RepoConfig,
|
||||||
addr: Addr<RepoActor>,
|
addr: Addr<RepoActor>,
|
||||||
|
git: Git,
|
||||||
net: network::Network,
|
net: network::Network,
|
||||||
) {
|
) {
|
||||||
let commit_histories = match repo_details.forge.forge_type {
|
let commit_histories = match repo_details.forge.forge_type {
|
||||||
|
@ -45,9 +39,11 @@ pub async fn validate_positions(
|
||||||
let next_is_ancestor_of_dev = commit_histories.dev.iter().any(|dev| dev == &next);
|
let next_is_ancestor_of_dev = commit_histories.dev.iter().any(|dev| dev == &next);
|
||||||
if !next_is_ancestor_of_dev {
|
if !next_is_ancestor_of_dev {
|
||||||
info!("Next is not an ancestor of dev - resetting next to main");
|
info!("Next is not an ancestor of dev - resetting next to main");
|
||||||
if branch::reset(
|
|
||||||
|
if git
|
||||||
|
.reset(
|
||||||
&config.branches().next(),
|
&config.branches().next(),
|
||||||
main,
|
main.into(),
|
||||||
ResetForce::Force(next.into()),
|
ResetForce::Force(next.into()),
|
||||||
&repo_details,
|
&repo_details,
|
||||||
)
|
)
|
||||||
|
@ -118,6 +114,7 @@ pub async fn advance_next(
|
||||||
repo_details: config::RepoDetails,
|
repo_details: config::RepoDetails,
|
||||||
repo_config: config::RepoConfig,
|
repo_config: config::RepoConfig,
|
||||||
addr: Addr<RepoActor>,
|
addr: Addr<RepoActor>,
|
||||||
|
git: Git,
|
||||||
) {
|
) {
|
||||||
let next_commit = find_next_commit_on_dev(next, dev_commit_history);
|
let next_commit = find_next_commit_on_dev(next, dev_commit_history);
|
||||||
let Some(commit) = next_commit else {
|
let Some(commit) = next_commit else {
|
||||||
|
@ -129,9 +126,9 @@ pub async fn advance_next(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
info!("Advancing next to commit '{}'", commit);
|
info!("Advancing next to commit '{}'", commit);
|
||||||
match reset(
|
match git.reset(
|
||||||
&repo_config.branches().next(),
|
&repo_config.branches().next(),
|
||||||
commit,
|
commit.into(),
|
||||||
ResetForce::None,
|
ResetForce::None,
|
||||||
&repo_details,
|
&repo_details,
|
||||||
) {
|
) {
|
||||||
|
@ -184,11 +181,12 @@ pub async fn advance_main(
|
||||||
next: forge::Commit,
|
next: forge::Commit,
|
||||||
repo_details: config::RepoDetails,
|
repo_details: config::RepoDetails,
|
||||||
repo_config: config::RepoConfig,
|
repo_config: config::RepoConfig,
|
||||||
|
git: Git,
|
||||||
) {
|
) {
|
||||||
info!("Advancing main to next");
|
info!("Advancing main to next");
|
||||||
match reset(
|
match git.reset(
|
||||||
&repo_config.branches().main(),
|
&repo_config.branches().main(),
|
||||||
next,
|
next.into(),
|
||||||
ResetForce::None,
|
ResetForce::None,
|
||||||
&repo_details,
|
&repo_details,
|
||||||
) {
|
) {
|
||||||
|
@ -201,75 +199,6 @@ pub async fn advance_main(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct GitRef(pub String);
|
|
||||||
impl From<forge::Commit> for GitRef {
|
|
||||||
fn from(value: forge::Commit) -> Self {
|
|
||||||
Self(value.sha().to_string())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl From<BranchName> for GitRef {
|
|
||||||
fn from(value: BranchName) -> Self {
|
|
||||||
Self(value.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Display for GitRef {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(f, "{}", self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum ResetForce {
|
|
||||||
None,
|
|
||||||
Force(GitRef),
|
|
||||||
}
|
|
||||||
impl Display for ResetForce {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(f, "{:?}", self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn reset(
|
|
||||||
branch: &BranchName,
|
|
||||||
gitref: impl Into<GitRef>,
|
|
||||||
reset_force: ResetForce,
|
|
||||||
repo_details: &config::RepoDetails,
|
|
||||||
) -> Result<(), std::io::Error> {
|
|
||||||
let gitref: GitRef = gitref.into();
|
|
||||||
let user = &repo_details.forge.user;
|
|
||||||
|
|
||||||
let hostname = &repo_details.forge.hostname;
|
|
||||||
let path = &repo_details.repo;
|
|
||||||
let token = &repo_details.forge.token.expose_secret();
|
|
||||||
let origin = format!("https://{user}:{token}@{hostname}/{path}.git");
|
|
||||||
let force = match reset_force {
|
|
||||||
ResetForce::None => "".to_string(),
|
|
||||||
ResetForce::Force(old_ref) => format!("--force-with-lease={branch}:{old_ref}"),
|
|
||||||
};
|
|
||||||
// INFO: never log the command as it contains the API token
|
|
||||||
let command = format!("/usr/bin/git push {origin} {gitref}:{branch} {force}");
|
|
||||||
drop(origin);
|
|
||||||
info!("Resetting {branch} to {gitref}");
|
|
||||||
match gix::command::prepare(command)
|
|
||||||
.with_shell_allow_argument_splitting()
|
|
||||||
.stdout(std::process::Stdio::null())
|
|
||||||
.stderr(std::process::Stdio::null())
|
|
||||||
.spawn()
|
|
||||||
{
|
|
||||||
Ok(mut child) => match child.wait() {
|
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(err) => {
|
|
||||||
warn!(?err, "Advance Next Failed (wait)");
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(err) => {
|
|
||||||
warn!(?err, "Advance Next Failed (spawn)");
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -10,6 +10,7 @@ use tracing::{info, warn};
|
||||||
use crate::server::{
|
use crate::server::{
|
||||||
config::{RepoConfig, RepoDetails},
|
config::{RepoConfig, RepoDetails},
|
||||||
forge,
|
forge,
|
||||||
|
git::Git,
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::webhook::WebhookId;
|
use self::webhook::WebhookId;
|
||||||
|
@ -19,14 +20,16 @@ pub struct RepoActor {
|
||||||
config: Option<RepoConfig>, // INFO: if [None] then send [StartRepo] to populate it
|
config: Option<RepoConfig>, // INFO: if [None] then send [StartRepo] to populate it
|
||||||
webhook_id: Option<WebhookId>, // INFO: if [None] then no webhook is configured
|
webhook_id: Option<WebhookId>, // INFO: if [None] then no webhook is configured
|
||||||
net: Network,
|
net: Network,
|
||||||
|
git: Git,
|
||||||
}
|
}
|
||||||
impl RepoActor {
|
impl RepoActor {
|
||||||
pub(crate) const fn new(details: RepoDetails, net: Network) -> Self {
|
pub(crate) const fn new(details: RepoDetails, net: Network, git: Git) -> Self {
|
||||||
Self {
|
Self {
|
||||||
details,
|
details,
|
||||||
config: None,
|
config: None,
|
||||||
webhook_id: None,
|
webhook_id: None,
|
||||||
net,
|
net,
|
||||||
|
git,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,7 +88,8 @@ impl Handler<ValidateRepo> for RepoActor {
|
||||||
let repo_details = self.details.clone();
|
let repo_details = self.details.clone();
|
||||||
let addr = ctx.address();
|
let addr = ctx.address();
|
||||||
let net = self.net.clone();
|
let net = self.net.clone();
|
||||||
branch::validate_positions(repo_details, repo_config, addr, net)
|
let git = self.git.clone();
|
||||||
|
branch::validate_positions(repo_details, repo_config, addr, git, net)
|
||||||
.into_actor(self)
|
.into_actor(self)
|
||||||
.wait(ctx);
|
.wait(ctx);
|
||||||
}
|
}
|
||||||
|
@ -115,6 +119,7 @@ impl Handler<StartMonitoring> for RepoActor {
|
||||||
let repo_details = self.details.clone();
|
let repo_details = self.details.clone();
|
||||||
let addr = ctx.address();
|
let addr = ctx.address();
|
||||||
let net = self.net.clone();
|
let net = self.net.clone();
|
||||||
|
let git = self.git.clone();
|
||||||
|
|
||||||
if next_ahead_of_main {
|
if next_ahead_of_main {
|
||||||
status::check_next(msg.next, repo_details, addr, net)
|
status::check_next(msg.next, repo_details, addr, net)
|
||||||
|
@ -127,6 +132,7 @@ impl Handler<StartMonitoring> for RepoActor {
|
||||||
repo_details,
|
repo_details,
|
||||||
repo_config,
|
repo_config,
|
||||||
addr,
|
addr,
|
||||||
|
git,
|
||||||
)
|
)
|
||||||
.into_actor(self)
|
.into_actor(self)
|
||||||
.wait(ctx);
|
.wait(ctx);
|
||||||
|
@ -159,7 +165,8 @@ impl Handler<AdvanceMainTo> for RepoActor {
|
||||||
warn!("No config loaded");
|
warn!("No config loaded");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
branch::advance_main(msg.0, repo_details, repo_config)
|
let git = self.git.clone();
|
||||||
|
branch::advance_main(msg.0, repo_details, repo_config, git)
|
||||||
.into_actor(self)
|
.into_actor(self)
|
||||||
.wait(ctx);
|
.wait(ctx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,7 +205,7 @@ impl Display for RepoPath {
|
||||||
write!(f, "{}", self.0)
|
write!(f, "{}", self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||||
pub struct BranchName(pub String);
|
pub struct BranchName(pub String);
|
||||||
impl Display for BranchName {
|
impl Display for BranchName {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
|
47
src/server/git/mock.rs
Normal file
47
src/server/git/mock.rs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::server::{
|
||||||
|
config::{BranchName, RepoDetails},
|
||||||
|
git::GitResetResult,
|
||||||
|
types::{GitRef, ResetForce},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct MockGit {
|
||||||
|
reset: HashMap<(BranchName, GitRef), GitResetResult>,
|
||||||
|
}
|
||||||
|
impl MockGit {
|
||||||
|
pub(super) fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
reset: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[allow(dead_code)] // TODO: (#38) Add tests
|
||||||
|
pub const fn into_git(self) -> super::Git {
|
||||||
|
super::Git::Mock(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)] // TODO: (#38) Add tests
|
||||||
|
pub fn expect_reset_result(
|
||||||
|
&mut self,
|
||||||
|
branch_name: &BranchName,
|
||||||
|
gitref: &GitRef,
|
||||||
|
result: GitResetResult,
|
||||||
|
) {
|
||||||
|
self.reset
|
||||||
|
.insert((branch_name.clone(), gitref.clone()), result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl super::GitLike for MockGit {
|
||||||
|
fn reset(
|
||||||
|
&self,
|
||||||
|
branch: &BranchName,
|
||||||
|
gitref: GitRef,
|
||||||
|
_reset_force: ResetForce,
|
||||||
|
_repo_details: &RepoDetails,
|
||||||
|
) -> GitResetResult {
|
||||||
|
self.reset
|
||||||
|
.get(&(branch.clone(), gitref.clone()))
|
||||||
|
.map_or_else(|| panic!("unexpected: {} to {}", branch, gitref), |r| *r)
|
||||||
|
}
|
||||||
|
}
|
48
src/server/git/mod.rs
Normal file
48
src/server/git/mod.rs
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
use crate::server::{
|
||||||
|
config::{BranchName, RepoDetails},
|
||||||
|
git::{mock::MockGit, real::RealGit},
|
||||||
|
types::{GitRef, ResetForce},
|
||||||
|
};
|
||||||
|
|
||||||
|
mod mock;
|
||||||
|
mod real;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum Git {
|
||||||
|
Real(RealGit),
|
||||||
|
#[allow(dead_code)] // TODO: (#38) Add tests
|
||||||
|
Mock(MockGit),
|
||||||
|
}
|
||||||
|
impl Git {
|
||||||
|
pub const fn new_real() -> Self {
|
||||||
|
Self::Real(RealGit::new())
|
||||||
|
}
|
||||||
|
#[allow(dead_code)] // TODO: (#38) Add tests
|
||||||
|
pub fn new_mock() -> MockGit {
|
||||||
|
MockGit::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Deref for Git {
|
||||||
|
type Target = dyn GitLike;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
match self {
|
||||||
|
Self::Real(git) => git,
|
||||||
|
Self::Mock(git) => git,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait GitLike: Sync + Send {
|
||||||
|
fn reset(
|
||||||
|
&self,
|
||||||
|
branch: &BranchName,
|
||||||
|
gitref: GitRef,
|
||||||
|
reset_force: ResetForce,
|
||||||
|
repo_details: &RepoDetails,
|
||||||
|
) -> GitResetResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type GitResetResult = Result<(), ()>;
|
57
src/server/git/real.rs
Normal file
57
src/server/git/real.rs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
use secrecy::ExposeSecret;
|
||||||
|
use tracing::{info, warn};
|
||||||
|
|
||||||
|
use crate::server::{
|
||||||
|
config::{BranchName, RepoDetails},
|
||||||
|
git::GitResetResult,
|
||||||
|
types::{GitRef, ResetForce},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct RealGit;
|
||||||
|
impl RealGit {
|
||||||
|
pub(super) const fn new() -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl super::GitLike for RealGit {
|
||||||
|
fn reset(
|
||||||
|
&self,
|
||||||
|
branch: &BranchName,
|
||||||
|
gitref: GitRef,
|
||||||
|
reset_force: ResetForce,
|
||||||
|
repo_details: &RepoDetails,
|
||||||
|
) -> GitResetResult {
|
||||||
|
let user = &repo_details.forge.user;
|
||||||
|
let hostname = &repo_details.forge.hostname;
|
||||||
|
let path = &repo_details.repo;
|
||||||
|
let token = &repo_details.forge.token.expose_secret();
|
||||||
|
let origin = format!("https://{user}:{token}@{hostname}/{path}.git");
|
||||||
|
let force = match reset_force {
|
||||||
|
ResetForce::None => "".to_string(),
|
||||||
|
ResetForce::Force(old_ref) => format!("--force-with-lease={branch}:{old_ref}"),
|
||||||
|
};
|
||||||
|
// INFO: never log the command as it contains the API token
|
||||||
|
let command = format!("/usr/bin/git push {origin} {gitref}:{branch} {force}");
|
||||||
|
drop(origin);
|
||||||
|
info!("Resetting {branch} to {gitref}");
|
||||||
|
match gix::command::prepare(command)
|
||||||
|
.with_shell_allow_argument_splitting()
|
||||||
|
.stdout(std::process::Stdio::null())
|
||||||
|
.stderr(std::process::Stdio::null())
|
||||||
|
.spawn()
|
||||||
|
{
|
||||||
|
Ok(mut child) => match child.wait() {
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
Err(err) => {
|
||||||
|
warn!(?err, "Failed (wait)");
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
warn!(?err, "Failed (spawn)");
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
mod actors;
|
mod actors;
|
||||||
mod config;
|
mod config;
|
||||||
pub mod forge;
|
pub mod forge;
|
||||||
|
pub mod git;
|
||||||
|
pub mod types;
|
||||||
|
|
||||||
use actix::prelude::*;
|
use actix::prelude::*;
|
||||||
use kxio::network::Network;
|
use kxio::network::Network;
|
||||||
|
@ -11,7 +13,10 @@ use tracing::{error, info, level_filters::LevelFilter};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
filesystem::FileSystem,
|
filesystem::FileSystem,
|
||||||
server::config::{Forge, ForgeName, RepoName},
|
server::{
|
||||||
|
config::{Forge, ForgeName, RepoName},
|
||||||
|
git::Git,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::{actors::repo::RepoActor, config::Repo};
|
use self::{actors::repo::RepoActor, config::Repo};
|
||||||
|
@ -34,7 +39,7 @@ pub fn init(fs: FileSystem) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn start(fs: FileSystem, net: Network) {
|
pub async fn start(fs: FileSystem, net: Network, git: Git) {
|
||||||
let Ok(_) = init_logging() else {
|
let Ok(_) = init_logging() else {
|
||||||
eprintln!("Failed to initialize logging.");
|
eprintln!("Failed to initialize logging.");
|
||||||
return;
|
return;
|
||||||
|
@ -51,7 +56,7 @@ pub async fn start(fs: FileSystem, net: Network) {
|
||||||
info!("Config loaded");
|
info!("Config loaded");
|
||||||
let addresses = config
|
let addresses = config
|
||||||
.forges()
|
.forges()
|
||||||
.flat_map(|(forge_name, forge)| create_forge_repos(forge, forge_name, &net))
|
.flat_map(|(forge_name, forge)| create_forge_repos(forge, forge_name, &net, &git))
|
||||||
.map(start_actor)
|
.map(start_actor)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let _ = actix_rt::signal::ctrl_c().await;
|
let _ = actix_rt::signal::ctrl_c().await;
|
||||||
|
@ -63,6 +68,7 @@ fn create_forge_repos(
|
||||||
forge: &Forge,
|
forge: &Forge,
|
||||||
forge_name: ForgeName,
|
forge_name: ForgeName,
|
||||||
net: &Network,
|
net: &Network,
|
||||||
|
git: &Git,
|
||||||
) -> Vec<(ForgeName, RepoName, RepoActor)> {
|
) -> Vec<(ForgeName, RepoName, RepoActor)> {
|
||||||
let forge = forge.clone();
|
let forge = forge.clone();
|
||||||
let span = tracing::info_span!("Forge", %forge_name, %forge);
|
let span = tracing::info_span!("Forge", %forge_name, %forge);
|
||||||
|
@ -70,7 +76,7 @@ fn create_forge_repos(
|
||||||
info!("Creating Forge");
|
info!("Creating Forge");
|
||||||
forge
|
forge
|
||||||
.repos()
|
.repos()
|
||||||
.map(create_actor(forge_name, forge.clone(), net))
|
.map(create_actor(forge_name, forge.clone(), net, git))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,8 +84,10 @@ fn create_actor(
|
||||||
forge_name: ForgeName,
|
forge_name: ForgeName,
|
||||||
forge: config::Forge,
|
forge: config::Forge,
|
||||||
net: &Network,
|
net: &Network,
|
||||||
|
git: &Git,
|
||||||
) -> impl Fn((RepoName, &Repo)) -> (ForgeName, RepoName, RepoActor) {
|
) -> impl Fn((RepoName, &Repo)) -> (ForgeName, RepoName, RepoActor) {
|
||||||
let net = net.clone();
|
let net = net.clone();
|
||||||
|
let git = git.clone();
|
||||||
move |(repo_name, repo)| {
|
move |(repo_name, repo)| {
|
||||||
let span = tracing::info_span!("Repo", %repo_name, %repo);
|
let span = tracing::info_span!("Repo", %repo_name, %repo);
|
||||||
let _guard = span.enter();
|
let _guard = span.enter();
|
||||||
|
@ -87,6 +95,7 @@ fn create_actor(
|
||||||
let actor = actors::repo::RepoActor::new(
|
let actor = actors::repo::RepoActor::new(
|
||||||
config::RepoDetails::new(&repo_name, repo, &forge_name, &forge),
|
config::RepoDetails::new(&repo_name, repo, &forge_name, &forge),
|
||||||
net.clone(),
|
net.clone(),
|
||||||
|
git.clone(),
|
||||||
);
|
);
|
||||||
info!("Created Repo");
|
info!("Created Repo");
|
||||||
(forge_name.clone(), repo_name, actor)
|
(forge_name.clone(), repo_name, actor)
|
||||||
|
|
32
src/server/types.rs
Normal file
32
src/server/types.rs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
use crate::server::{config::BranchName, forge};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||||
|
pub struct GitRef(pub String);
|
||||||
|
impl From<forge::Commit> for GitRef {
|
||||||
|
fn from(value: forge::Commit) -> Self {
|
||||||
|
Self(value.sha().to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<BranchName> for GitRef {
|
||||||
|
fn from(value: BranchName) -> Self {
|
||||||
|
Self(value.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Display for GitRef {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ResetForce {
|
||||||
|
None,
|
||||||
|
Force(GitRef),
|
||||||
|
}
|
||||||
|
impl Display for ResetForce {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{:?}", self)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue