From a4df70c42296997a05b9d7bad15fb1e779a3e387 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Sat, 7 Sep 2024 21:03:33 +0200 Subject: [PATCH] refactor clone for clarity --- crates/gitbutler-tauri/src/error.rs | 35 ++++++++++++++++++++++++++++- crates/gitbutler-tauri/src/repo.rs | 26 +++++++++------------ 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/crates/gitbutler-tauri/src/error.rs b/crates/gitbutler-tauri/src/error.rs index c7dec7a3d2..9a1a6c95cd 100644 --- a/crates/gitbutler-tauri/src/error.rs +++ b/crates/gitbutler-tauri/src/error.rs @@ -13,7 +13,7 @@ //! //! The values in these fields are controlled by attaching context, please [see the `error` docs](gitbutler_error::error)) //! on how to do this. -pub(crate) use frontend::Error; +pub(crate) use frontend::{Error, UnmarkedError}; mod frontend { use std::borrow::Cow; @@ -21,6 +21,39 @@ mod frontend { use gitbutler_error::error::AnyhowContextExt; use serde::{ser::SerializeMap, Serialize}; + /// An error type for serialization which isn't expected to carry a code. + #[derive(Debug)] + pub struct UnmarkedError(anyhow::Error); + + impl From for UnmarkedError + where + T: std::error::Error + Send + Sync + 'static, + { + fn from(err: T) -> Self { + Self(err.into()) + } + } + + impl Serialize for UnmarkedError { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let ctx = self.0.custom_context_or_root_cause(); + + let mut map = serializer.serialize_map(Some(2))?; + map.serialize_entry("code", &ctx.code.to_string())?; + let message = ctx.message.unwrap_or_else(|| { + self.0 + .source() + .map(|err| Cow::Owned(err.to_string())) + .unwrap_or_else(|| Cow::Borrowed("Something went wrong")) + }); + map.serialize_entry("message", &message)?; + map.end() + } + } + /// An error type for serialization, dynamically extracting context information during serialization, /// meant for consumption by the frontend. #[derive(Debug)] diff --git a/crates/gitbutler-tauri/src/repo.rs b/crates/gitbutler-tauri/src/repo.rs index d52d50bffb..27c0d0f33d 100644 --- a/crates/gitbutler-tauri/src/repo.rs +++ b/crates/gitbutler-tauri/src/repo.rs @@ -1,16 +1,15 @@ pub mod commands { - use anyhow::{Context, Result}; + use anyhow::Result; use gitbutler_branch_actions::RemoteBranchFile; use gitbutler_project as projects; use gitbutler_project::ProjectId; use gitbutler_repo::RepoCommands; - use gix::progress::Discard; use std::path::Path; use std::sync::atomic::AtomicBool; use tauri::State; use tracing::instrument; - use crate::error::Error; + use crate::error::{Error, UnmarkedError}; #[tauri::command(async)] #[instrument(skip(projects), err(Debug))] @@ -46,19 +45,16 @@ pub mod commands { } #[tauri::command(async)] - pub fn git_clone_repository(repository_url: &str, target_dir: &Path) -> Result<(), Error> { - let url = - gix::url::parse(repository_url.into()).context("Failed to parse repository URL")?; + pub fn git_clone_repository( + repository_url: &str, + target_dir: &Path, + ) -> Result<(), UnmarkedError> { let should_interrupt = AtomicBool::new(false); - let mut prepared_clone = - gix::prepare_clone(url, target_dir).context("Failed to prepare clone")?; - let (mut prepared_checkout, _) = prepared_clone - .fetch_then_checkout(Discard, &should_interrupt) - .context("Failed to fetch")?; - let should_interrupt = AtomicBool::new(false); - prepared_checkout - .main_worktree(Discard, &should_interrupt) - .context("Failed to checkout main worktree")?; + + gix::prepare_clone(repository_url, target_dir)? + .fetch_then_checkout(gix::progress::Discard, &should_interrupt) + .map(|(checkout, _outcome)| checkout)? + .main_worktree(gix::progress::Discard, &should_interrupt)?; Ok(()) }