Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion crates/gitbutler-tauri/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,47 @@
//!
//! 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;

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<T> From<T> for UnmarkedError
where
T: std::error::Error + Send + Sync + 'static,
{
fn from(err: T) -> Self {
Self(err.into())
}
}

impl Serialize for UnmarkedError {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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)]
Expand Down
26 changes: 11 additions & 15 deletions crates/gitbutler-tauri/src/repo.rs
Original file line number Diff line number Diff line change
@@ -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))]
Expand Down Expand Up @@ -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(())
}

Expand Down