From 83679206cde2a3f3d16fe19d481f88de8ff70983 Mon Sep 17 00:00:00 2001 From: Kiril Videlov Date: Tue, 30 Jul 2024 21:29:54 +0200 Subject: [PATCH] separate syncing of oplog from regular refs --- crates/gitbutler-project/src/project.rs | 25 +++++++++- crates/gitbutler-sync/src/cloud.rs | 64 +++++++++++++++---------- crates/gitbutler-watcher/src/handler.rs | 14 +++--- 3 files changed, 71 insertions(+), 32 deletions(-) diff --git a/crates/gitbutler-project/src/project.rs b/crates/gitbutler-project/src/project.rs index cde58589a..dfa7e58a8 100644 --- a/crates/gitbutler-project/src/project.rs +++ b/crates/gitbutler-project/src/project.rs @@ -26,11 +26,17 @@ pub struct ApiProject { pub name: String, pub description: Option, pub repository_id: String, + /// The "gitbuler data, i.e. oplog" URL pub git_url: String, + /// The "project" git URL pub code_git_url: Option, pub created_at: String, pub updated_at: String, + /// Determines if the project Operations log will be synched with the GitButHub pub sync: bool, + /// Determines if the project code will be synched with the GitButHub + #[serde(default)] + pub sync_code: bool, } #[derive(Debug, Deserialize, Serialize, Clone)] @@ -93,8 +99,23 @@ pub struct Project { } impl Project { - pub fn is_sync_enabled(&self) -> bool { - self.api.as_ref().map(|api| api.sync).unwrap_or_default() + /// Determines if the project Operations log will be synched with the GitButHub + pub fn oplog_sync_enabled(&self) -> bool { + let has_url = self.api.as_ref().map(|api| api.git_url.clone()).is_some(); + self.api.as_ref().map(|api| api.sync).unwrap_or_default() && has_url + } + /// Determines if the project code will be synched with the GitButHub + pub fn code_sync_enabled(&self) -> bool { + let has_code_url = self + .api + .as_ref() + .and_then(|api| api.code_git_url.clone()) + .is_some(); + self.api + .as_ref() + .map(|api| api.sync_code) + .unwrap_or_default() + && has_code_url } pub fn has_code_url(&self) -> bool { diff --git a/crates/gitbutler-sync/src/cloud.rs b/crates/gitbutler-sync/src/cloud.rs index e6f4a412d..f5fa34bc7 100644 --- a/crates/gitbutler-sync/src/cloud.rs +++ b/crates/gitbutler-sync/src/cloud.rs @@ -16,7 +16,8 @@ use gitbutler_url::Url; use gitbutler_user as users; use itertools::Itertools; -pub fn sync_with_gitbutler( +/// Pushes the repository to the GitButler remote +pub fn push_repo( ctx: &CommandContext, user: &users::User, projects: &projects::Controller, @@ -43,18 +44,25 @@ pub fn sync_with_gitbutler( // Push all refs push_all_refs(ctx, user, project.id)?; + Ok(()) +} +/// Pushes the Oplog head to GitButler server +pub fn push_oplog(ctx: &CommandContext, user: &users::User) -> Result<()> { // Push Oplog head let oplog_refspec = ctx .project() .oplog_head()? - .map(|sha| format!("+{}:refs/gitbutler/oplog/oplog", sha)); + .map(|sha| format!("+{}:refs/gitbutler/oplog", sha)); if let Some(oplog_refspec) = oplog_refspec { - let x = push_to_gitbutler_server(ctx, Some(user), &[&oplog_refspec]); - println!("\n\n\nHERE: {:?}", x?); + push_to_gitbutler_server( + ctx, + Some(user), + &[&oplog_refspec], + remote(ctx, RemoteKind::Oplog)?, + )?; } - Ok(()) } @@ -80,11 +88,12 @@ fn push_target( "batches left to push", ); + let remote = remote(ctx, RemoteKind::Code)?; let id_count = ids.len(); for (idx, id) in ids.iter().enumerate().rev() { let refspec = format!("+{}:refs/push-tmp/{}", id, project_id); - push_to_gitbutler_server(ctx, Some(user), &[&refspec])?; + push_to_gitbutler_server(ctx, Some(user), &[&refspec], remote.clone())?; update_project(projects, project_id, *id)?; tracing::info!( @@ -99,6 +108,7 @@ fn push_target( ctx, Some(user), &[&format!("+{}:refs/{}", default_target.sha, project_id)], + remote.clone(), )?; //TODO: remove push-tmp ref @@ -168,7 +178,8 @@ fn push_all_refs( let all_refs: Vec<_> = all_refs.iter().map(String::as_str).collect(); - let anything_pushed = push_to_gitbutler_server(ctx, Some(user), &all_refs)?; + let anything_pushed = + push_to_gitbutler_server(ctx, Some(user), &all_refs, remote(ctx, RemoteKind::Code)?)?; if anything_pushed { tracing::info!( %project_id, @@ -199,23 +210,9 @@ fn push_to_gitbutler_server( ctx: &CommandContext, user: Option<&users::User>, ref_specs: &[&str], + mut remote: git2::Remote, ) -> Result { let project = ctx.project(); - let url = project - .api - .as_ref() - .context("api not set")? - .code_git_url - .as_ref() - .context("code_git_url not set")? - .as_str() - .parse::()?; - - tracing::debug!( - project_id = %project.id, - %url, - "pushing code to gb repo", - ); let user = user .context("need user to push to gitbutler") @@ -243,8 +240,6 @@ fn push_to_gitbutler_server( let headers = &[auth_header.as_str()]; push_options.custom_headers(headers); - let mut remote = ctx.repository().remote_anonymous(&url.to_string())?; - remote .push(ref_specs, Some(&mut push_options)) .map_err(|err| match err.class() { @@ -270,3 +265,24 @@ fn push_to_gitbutler_server( Ok(total_objects_pushed > 0) } + +enum RemoteKind { + Code, + Oplog, +} +fn remote(ctx: &CommandContext, kind: RemoteKind) -> Result { + let api_project = ctx.project().api.as_ref().context("api not set")?; + let url = match kind { + RemoteKind::Code => { + let url = api_project + .code_git_url + .as_ref() + .context("code_git_url not set")?; + url.as_str().parse::() + } + RemoteKind::Oplog => api_project.git_url.as_str().parse::(), + }?; + ctx.repository() + .remote_anonymous(&url.to_string()) + .map_err(Into::into) +} diff --git a/crates/gitbutler-watcher/src/handler.rs b/crates/gitbutler-watcher/src/handler.rs index 6c6452136..1a9ce25b6 100644 --- a/crates/gitbutler-watcher/src/handler.rs +++ b/crates/gitbutler-watcher/src/handler.rs @@ -12,7 +12,7 @@ use gitbutler_oplog::{ use gitbutler_project as projects; use gitbutler_project::ProjectId; use gitbutler_reference::{LocalRefname, Refname}; -use gitbutler_sync::cloud::sync_with_gitbutler; +use gitbutler_sync::cloud::{push_oplog, push_repo}; use gitbutler_user as users; use tracing::instrument; @@ -204,11 +204,13 @@ impl Handler { .get(project_id) .context("failed to get project")?; - if project.is_sync_enabled() && project.has_code_url() { - if let Some(user) = self.users.get_user()? { - let repository = CommandContext::open(&project) - .context("failed to open project repository for project")?; - return sync_with_gitbutler(&repository, &user, &self.projects); + if let Some(user) = self.users.get_user()? { + let ctx = CommandContext::open(&project)?; + if project.oplog_sync_enabled() { + push_oplog(&ctx, &user)?; + } + if project.code_sync_enabled() { + push_repo(&ctx, &user, &self.projects)?; } } Ok(())