From 992821d563ade9ca109cd400614c28913b9ccf5e Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Thu, 9 May 2024 21:18:40 +0100 Subject: [PATCH] feat(server): cache Repository in RepoActor --- src/server/actors/repo/mod.rs | 7 +++++-- src/server/gitforge/errors.rs | 7 +++++++ src/server/gitforge/forgejo/mod.rs | 15 +++++++++------ src/server/gitforge/forgejo/repo/clone.rs | 8 ++++---- src/server/gitforge/forgejo/repo/mod.rs | 2 ++ src/server/gitforge/forgejo/repo/open.rs | 8 ++++++++ src/server/gitforge/mock_forge.rs | 4 ++-- src/server/gitforge/mod.rs | 2 +- src/server/gitforge/types.rs | 3 +++ 9 files changed, 41 insertions(+), 15 deletions(-) create mode 100644 src/server/gitforge/forgejo/repo/open.rs diff --git a/src/server/actors/repo/mod.rs b/src/server/actors/repo/mod.rs index 202a04f..4656fea 100644 --- a/src/server/actors/repo/mod.rs +++ b/src/server/actors/repo/mod.rs @@ -10,7 +10,7 @@ use tracing::{debug, info, warn, Instrument}; use crate::server::{ actors::repo::webhook::WebhookAuth, config::{RepoConfig, RepoDetails, Webhook}, - gitforge, + gitforge::{self, Repository}, types::{MessageToken, ServerGeneration}, }; @@ -26,6 +26,7 @@ pub struct RepoActor { last_main_commit: Option, last_next_commit: Option, last_dev_commit: Option, + repository: Option, net: Network, forge: gitforge::Forge, } @@ -55,6 +56,7 @@ impl RepoActor { last_main_commit: None, last_next_commit: None, last_dev_commit: None, + repository: None, net, forge, } @@ -100,7 +102,8 @@ impl Handler for RepoActor { info!("Message Received"); let gitdir = self.details.gitdir.clone(); match self.forge.repo_clone(gitdir) { - Ok(_) => { + Ok(repository) => { + self.repository.replace(repository); if self.details.repo_config.is_none() { ctx.address().do_send(LoadConfigFromRepo); } else { diff --git a/src/server/gitforge/errors.rs b/src/server/gitforge/errors.rs index de7064f..3eadea0 100644 --- a/src/server/gitforge/errors.rs +++ b/src/server/gitforge/errors.rs @@ -48,6 +48,7 @@ pub enum RepoCloneError { Spawn(std::io::Error), Validation(String), GixClone(Box), + GixOpen(Box), GixFetch(Box), } impl std::error::Error for RepoCloneError {} @@ -60,6 +61,7 @@ impl std::fmt::Display for RepoCloneError { Self::Spawn(err) => write!(f, "Spawning comming: {:?}", err), Self::Validation(err) => write!(f, "Validation: {}", err), Self::GixClone(err) => write!(f, "Clone: {:?}", err), + Self::GixOpen(err) => write!(f, "Open: {:?}", err), Self::GixFetch(err) => write!(f, "Fetch: {:?}", err), } } @@ -69,6 +71,11 @@ impl From for RepoCloneError { Self::GixClone(Box::new(value)) } } +impl From for RepoCloneError { + fn from(value: gix::open::Error) -> Self { + Self::GixOpen(Box::new(value)) + } +} impl From for RepoCloneError { fn from(value: gix::clone::fetch::Error) -> Self { Self::GixFetch(Box::new(value)) diff --git a/src/server/gitforge/forgejo/mod.rs b/src/server/gitforge/forgejo/mod.rs index cacfcbf..983f841 100644 --- a/src/server/gitforge/forgejo/mod.rs +++ b/src/server/gitforge/forgejo/mod.rs @@ -13,7 +13,7 @@ use crate::server::{ actors::repo::{RepoActor, StartMonitoring, ValidateRepo}, config::{BranchName, GitDir, RepoConfig, RepoDetails}, git, - gitforge::{self, forgejo::branch::ValidatedPositions, RepoCloneError}, + gitforge::{self, forgejo::branch::ValidatedPositions, RepoCloneError, Repository}, types::{GitRef, MessageToken}, }; @@ -128,16 +128,19 @@ impl super::ForgeLike for ForgeJoEnv { } } - fn repo_clone(&self, gitdir: GitDir) -> Result<(), RepoCloneError> { - if !gitdir.exists() { + fn repo_clone(&self, gitdir: GitDir) -> Result { + let repo = if !gitdir.exists() { info!("Local copy not found - cloning..."); - repo::clone(&self.repo_details, gitdir.clone())?; - } + repo::clone(&self.repo_details, gitdir.clone())? + } else { + repo::open(gitdir.clone())? + }; info!("Validating..."); gitdir .validate(&self.repo_details) .map_err(|e| RepoCloneError::Validation(e.to_string())) - .inspect(|_| info!("Validation - OK")) + .inspect(|_| info!("Validation - OK"))?; + Ok(repo) } } diff --git a/src/server/gitforge/forgejo/repo/clone.rs b/src/server/gitforge/forgejo/repo/clone.rs index 6309e50..7ea1dc2 100644 --- a/src/server/gitforge/forgejo/repo/clone.rs +++ b/src/server/gitforge/forgejo/repo/clone.rs @@ -4,17 +4,17 @@ use tracing::info; use crate::server::{ config::{GitDir, RepoDetails}, - gitforge::RepoCloneError, + gitforge::{RepoCloneError, Repository}, }; #[tracing::instrument(skip_all)] -pub fn clone(repo_details: &RepoDetails, gitdir: GitDir) -> Result<(), RepoCloneError> { +pub fn clone(repo_details: &RepoDetails, gitdir: GitDir) -> Result { use secrecy::ExposeSecret; let origin = repo_details.origin(); - let (_repository, _outcome) = + let (repository, _outcome) = gix::prepare_clone_bare(origin.expose_secret().as_str(), gitdir.deref())? .fetch_only(gix::progress::Discard, &AtomicBool::new(false))?; info!("Cloned - OK"); - Ok(()) // TODO: (#69) return Repository inside a newtype to store in the RepoActor for reuse else where + Ok(repository.into_sync().into()) } diff --git a/src/server/gitforge/forgejo/repo/mod.rs b/src/server/gitforge/forgejo/repo/mod.rs index bb5a180..df614ba 100644 --- a/src/server/gitforge/forgejo/repo/mod.rs +++ b/src/server/gitforge/forgejo/repo/mod.rs @@ -1,3 +1,5 @@ mod clone; +mod open; pub use clone::clone; +pub use open::open; diff --git a/src/server/gitforge/forgejo/repo/open.rs b/src/server/gitforge/forgejo/repo/open.rs new file mode 100644 index 0000000..c2235bd --- /dev/null +++ b/src/server/gitforge/forgejo/repo/open.rs @@ -0,0 +1,8 @@ +use crate::server::{ + config::GitDir, + gitforge::{RepoCloneError, Repository}, +}; + +pub fn open(gitdir: GitDir) -> Result { + Ok(gix::open(gitdir)?.into_sync().into()) +} diff --git a/src/server/gitforge/mock_forge.rs b/src/server/gitforge/mock_forge.rs index d44f1e3..0003322 100644 --- a/src/server/gitforge/mock_forge.rs +++ b/src/server/gitforge/mock_forge.rs @@ -1,7 +1,7 @@ use crate::server::{ actors::repo::RepoActor, config::{BranchName, GitDir, RepoConfig}, - gitforge::{self, RepoCloneError}, + gitforge::{self, RepoCloneError, Repository}, types::{GitRef, MessageToken}, }; @@ -53,7 +53,7 @@ impl super::ForgeLike for MockForgeEnv { todo!() } - fn repo_clone(&self, _gitdir: GitDir) -> Result<(), RepoCloneError> { + fn repo_clone(&self, _gitdir: GitDir) -> Result { todo!() } } diff --git a/src/server/gitforge/mod.rs b/src/server/gitforge/mod.rs index ba5136d..ad9b9fb 100644 --- a/src/server/gitforge/mod.rs +++ b/src/server/gitforge/mod.rs @@ -56,7 +56,7 @@ pub trait ForgeLike { async fn commit_status(&self, commit: &Commit) -> CommitStatus; /// Clones a repo to disk. - fn repo_clone(&self, gitdir: GitDir) -> Result<(), RepoCloneError>; + fn repo_clone(&self, gitdir: GitDir) -> Result; } #[derive(Clone, Debug)] diff --git a/src/server/gitforge/types.rs b/src/server/gitforge/types.rs index 407a020..9d4c3f7 100644 --- a/src/server/gitforge/types.rs +++ b/src/server/gitforge/types.rs @@ -96,3 +96,6 @@ impl std::fmt::Display for Message { write!(f, "{}", self.0) } } + +#[derive(Debug, Clone, derive_more::From)] +pub struct Repository(gix::ThreadSafeRepository);