From de2989f3526549f2bc90e54fc5122991d09ab4eb Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Fri, 9 Aug 2024 10:38:52 +0200 Subject: [PATCH] Don't use `gix` built-in serialization as it will leave BString as sequence of numbers. Instead, we need it to be a string, even if lossy. --- Cargo.lock | 96 ------------------- Cargo.toml | 2 +- crates/gitbutler-branch-actions/src/branch.rs | 14 +-- crates/gitbutler-branch-actions/src/commit.rs | 18 ++-- crates/gitbutler-branch-actions/src/hunk.rs | 5 +- crates/gitbutler-branch-actions/src/remote.rs | 10 +- crates/gitbutler-branch/Cargo.toml | 2 +- crates/gitbutler-branch/src/branch.rs | 15 ++- crates/gitbutler-diff/src/diff.rs | 9 +- crates/gitbutler-serde/src/bstring.rs | 72 ++++++++++++++ crates/gitbutler-serde/src/lib.rs | 17 +--- 11 files changed, 114 insertions(+), 146 deletions(-) create mode 100644 crates/gitbutler-serde/src/bstring.rs diff --git a/Cargo.lock b/Cargo.lock index f7e7b49b8..b77795fe1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -534,9 +534,6 @@ name = "bitflags" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" -dependencies = [ - "serde", -] [[package]] name = "bitvec" @@ -2578,7 +2575,6 @@ dependencies = [ "gix-index 0.33.1 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-lock 14.0.0 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-macros", - "gix-mailmap", "gix-negotiate", "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-odb", @@ -2586,7 +2582,6 @@ dependencies = [ "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-pathspec", "gix-prompt", - "gix-protocol", "gix-ref 0.45.0", "gix-refspec", "gix-revision", @@ -2595,14 +2590,12 @@ dependencies = [ "gix-submodule", "gix-tempfile 14.0.1 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", - "gix-transport", "gix-traverse 0.39.2 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-url", "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-validate 0.8.5 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-worktree 0.34.1 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "once_cell", - "serde", "smallvec", "thiserror", ] @@ -2630,7 +2623,6 @@ dependencies = [ "gix-date 0.9.0", "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "itoa 1.0.11", - "serde", "thiserror", "winnow 0.6.16", ] @@ -2663,7 +2655,6 @@ dependencies = [ "gix-quote 0.4.12 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "kstring", - "serde", "smallvec", "thiserror", "unicode-bom", @@ -2738,7 +2729,6 @@ dependencies = [ "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "memmap2", - "serde", "thiserror", ] @@ -2787,7 +2777,6 @@ dependencies = [ "gix-sec 0.10.7 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-url", - "serde", "thiserror", ] @@ -2811,7 +2800,6 @@ dependencies = [ "bstr", "itoa 1.0.11", "jiff", - "serde", "thiserror", ] @@ -2973,7 +2961,6 @@ dependencies = [ "bstr", "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", - "serde", ] [[package]] @@ -2992,7 +2979,6 @@ version = "0.14.2" source = "git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a#7dff44754e0fdc369f92221468fb953bad9be60a" dependencies = [ "faster-hex", - "serde", "thiserror", ] @@ -3039,7 +3025,6 @@ dependencies = [ "gix-glob 0.16.4 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", - "serde", "unicode-bom", ] @@ -3094,7 +3079,6 @@ dependencies = [ "libc", "memmap2", "rustix 0.38.34", - "serde", "smallvec", "thiserror", ] @@ -3130,18 +3114,6 @@ dependencies = [ "syn 2.0.68", ] -[[package]] -name = "gix-mailmap" -version = "0.23.5" -source = "git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a#7dff44754e0fdc369f92221468fb953bad9be60a" -dependencies = [ - "bstr", - "gix-actor 0.31.5 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", - "gix-date 0.9.0", - "serde", - "thiserror", -] - [[package]] name = "gix-negotiate" version = "0.13.2" @@ -3189,7 +3161,6 @@ dependencies = [ "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-validate 0.8.5 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "itoa 1.0.11", - "serde", "smallvec", "thiserror", "winnow 0.6.16", @@ -3210,7 +3181,6 @@ dependencies = [ "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-quote 0.4.12 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "parking_lot 0.12.3", - "serde", "tempfile", "thiserror", ] @@ -3228,23 +3198,11 @@ dependencies = [ "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "memmap2", - "serde", "smallvec", "thiserror", "uluru", ] -[[package]] -name = "gix-packetline" -version = "0.17.5" -source = "git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a#7dff44754e0fdc369f92221468fb953bad9be60a" -dependencies = [ - "bstr", - "faster-hex", - "gix-trace 0.1.9 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", - "thiserror", -] - [[package]] name = "gix-packetline-blocking" version = "0.17.4" @@ -3307,24 +3265,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "gix-protocol" -version = "0.45.2" -source = "git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a#7dff44754e0fdc369f92221468fb953bad9be60a" -dependencies = [ - "bstr", - "gix-credentials", - "gix-date 0.9.0", - "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", - "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", - "gix-transport", - "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", - "maybe-async", - "serde", - "thiserror", - "winnow 0.6.16", -] - [[package]] name = "gix-quote" version = "0.4.12" @@ -3384,7 +3324,6 @@ dependencies = [ "gix-utils 0.1.12 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-validate 0.8.5 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "memmap2", - "serde", "thiserror", "winnow 0.6.16", ] @@ -3412,7 +3351,6 @@ dependencies = [ "gix-hash 0.14.2 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-revwalk 0.13.2 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", - "serde", "thiserror", ] @@ -3465,7 +3403,6 @@ dependencies = [ "bitflags 2.6.0", "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "libc", - "serde", "windows-sys 0.52.0", ] @@ -3547,22 +3484,6 @@ name = "gix-trace" version = "0.1.9" source = "git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a#7dff44754e0fdc369f92221468fb953bad9be60a" -[[package]] -name = "gix-transport" -version = "0.42.2" -source = "git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a#7dff44754e0fdc369f92221468fb953bad9be60a" -dependencies = [ - "bstr", - "gix-command", - "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", - "gix-packetline", - "gix-quote 0.4.12 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", - "gix-sec 0.10.7 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", - "gix-url", - "serde", - "thiserror", -] - [[package]] name = "gix-traverse" version = "0.39.2" @@ -3605,7 +3526,6 @@ dependencies = [ "gix-features 0.38.2 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "home", - "serde", "thiserror", "url", ] @@ -3684,7 +3604,6 @@ dependencies = [ "gix-object 0.42.3 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-path 0.10.9 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", "gix-validate 0.8.5 (git+https://github.com/Byron/gitoxide?rev=7dff44754e0fdc369f92221468fb953bad9be60a)", - "serde", ] [[package]] @@ -4579,7 +4498,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec3066350882a1cd6d950d055997f379ac37fd39f81cd4d8ed186032eb3c5747" dependencies = [ - "serde", "static_assertions", ] @@ -4770,17 +4688,6 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" -[[package]] -name = "maybe-async" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.68", -] - [[package]] name = "md5" version = "0.7.0" @@ -6772,9 +6679,6 @@ name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" -dependencies = [ - "serde", -] [[package]] name = "socket2" diff --git a/Cargo.toml b/Cargo.toml index 0a2079146..a02bf4abb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,7 +35,7 @@ resolver = "2" [workspace.dependencies] bstr = "1.10.0" # Add the `tracing` or `tracing-detail` features to see more of gitoxide in the logs. Useful to see which programs it invokes. -gix = { git = "https://github.com/Byron/gitoxide", rev = "7dff44754e0fdc369f92221468fb953bad9be60a", default-features = false, features = ["serde"] } +gix = { git = "https://github.com/Byron/gitoxide", rev = "7dff44754e0fdc369f92221468fb953bad9be60a", default-features = false, features = [] } git2 = { version = "0.18.3", features = [ "vendored-openssl", "vendored-libgit2", diff --git a/crates/gitbutler-branch-actions/src/branch.rs b/crates/gitbutler-branch-actions/src/branch.rs index 9c05a80de..ea42bfb65 100644 --- a/crates/gitbutler-branch-actions/src/branch.rs +++ b/crates/gitbutler-branch-actions/src/branch.rs @@ -1,12 +1,13 @@ use crate::VirtualBranchesExt; use anyhow::{Context, Result}; -use bstr::{BStr, BString, ByteSlice}; +use bstr::{BStr, ByteSlice}; use core::fmt; use gitbutler_branch::{ Branch as GitButlerBranch, BranchId, BranchIdentity, ReferenceExtGix, Target, }; use gitbutler_command_context::CommandContext; use gitbutler_reference::normalize_branch_name; +use gitbutler_serde::BStringForFrontend; use gix::prelude::ObjectIdExt; use gix::reference::Category; use serde::{Deserialize, Serialize}; @@ -378,9 +379,9 @@ pub struct BranchListing { #[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)] pub struct Author { /// The name of the author as configured in the git config - pub name: Option, + pub name: Option, /// The email of the author as configured in the git config - pub email: Option, + pub email: Option, } impl From> for Author { @@ -394,8 +395,8 @@ impl From> for Author { impl From> for Author { fn from(value: gix::actor::SignatureRef<'_>) -> Self { Author { - name: Some(value.name.to_owned()), - email: Some(value.email.to_owned()), + name: Some(value.name.to_owned().into()), + email: Some(value.email.to_owned().into()), } } } @@ -557,8 +558,7 @@ pub struct CommitEntry { /// If the commit is referencing a specific change, this is its change id pub change_id: Option, /// The commit message - #[serde(serialize_with = "gitbutler_serde::as_string_lossy")] - pub description: BString, + pub description: BStringForFrontend, /// The timestamp of the commit in milliseconds pub created_at: u128, /// The author of the commit diff --git a/crates/gitbutler-branch-actions/src/commit.rs b/crates/gitbutler-branch-actions/src/commit.rs index f49ff4a4c..a9a296df5 100644 --- a/crates/gitbutler-branch-actions/src/commit.rs +++ b/crates/gitbutler-branch-actions/src/commit.rs @@ -1,14 +1,13 @@ -use anyhow::{Context, Result}; -use bstr::BString; -use gitbutler_branch::{Branch, BranchId}; -use gitbutler_command_context::CommandContext; -use gitbutler_commit::commit_ext::CommitExt; -use serde::Serialize; - use crate::{ author::Author, file::{list_virtual_commit_files, VirtualBranchFile}, }; +use anyhow::{Context, Result}; +use gitbutler_branch::{Branch, BranchId}; +use gitbutler_command_context::CommandContext; +use gitbutler_commit::commit_ext::CommitExt; +use gitbutler_serde::BStringForFrontend; +use serde::Serialize; // this is the struct that maps to the view `Commit` type in Typescript // it is derived from walking the git commits between the `Branch.head` commit @@ -23,8 +22,7 @@ use crate::{ pub struct VirtualBranchCommit { #[serde(with = "gitbutler_serde::oid")] pub id: git2::Oid, - #[serde(serialize_with = "gitbutler_serde::as_string_lossy")] - pub description: BString, + pub description: BStringForFrontend, pub created_at: u128, pub author: Author, pub is_remote: bool, @@ -62,7 +60,7 @@ pub(crate) fn commit_to_vbranch_commit( id: commit.id(), created_at: timestamp * 1000, author: commit.author().into(), - description: message, + description: message.into(), is_remote, files, is_integrated, diff --git a/crates/gitbutler-branch-actions/src/hunk.rs b/crates/gitbutler-branch-actions/src/hunk.rs index 724b47ef6..1cdf7ed4f 100644 --- a/crates/gitbutler-branch-actions/src/hunk.rs +++ b/crates/gitbutler-branch-actions/src/hunk.rs @@ -5,9 +5,9 @@ use std::{ time::SystemTime, }; -use bstr::BString; use gitbutler_branch::BranchId; use gitbutler_diff::{GitHunk, Hunk, HunkHash}; +use gitbutler_serde::BStringForFrontend; use itertools::Itertools; use md5::Digest; use serde::Serialize; @@ -24,8 +24,7 @@ use serde::Serialize; #[serde(rename_all = "camelCase")] pub struct VirtualBranchHunk { pub id: String, - #[serde(serialize_with = "gitbutler_serde::as_string_lossy")] - pub diff: BString, + pub diff: BStringForFrontend, pub modified_at: u128, pub file_path: PathBuf, #[serde(serialize_with = "gitbutler_branch::serde::hash_to_hex")] diff --git a/crates/gitbutler-branch-actions/src/remote.rs b/crates/gitbutler-branch-actions/src/remote.rs index 1d6ef3449..b6c49a4d2 100644 --- a/crates/gitbutler-branch-actions/src/remote.rs +++ b/crates/gitbutler-branch-actions/src/remote.rs @@ -1,16 +1,15 @@ use std::path::Path; +use crate::author::Author; use anyhow::{Context, Result}; -use bstr::BString; use gitbutler_branch::{ReferenceExt, Target, VirtualBranchesHandle}; use gitbutler_command_context::CommandContext; use gitbutler_commit::commit_ext::CommitExt; use gitbutler_reference::{Refname, RemoteRefname}; use gitbutler_repo::{LogUntil, RepoActionsExt, RepositoryExt}; +use gitbutler_serde::BStringForFrontend; use serde::Serialize; -use crate::author::Author; - // this struct is a mapping to the view `RemoteBranch` type in Typescript // found in src-tauri/src/routes/repo/[project_id]/types.ts // @@ -50,8 +49,7 @@ pub struct RemoteBranchData { #[serde(rename_all = "camelCase")] pub struct RemoteCommit { pub id: String, - #[serde(serialize_with = "gitbutler_serde::as_string_lossy")] - pub description: BString, + pub description: BStringForFrontend, pub created_at: u128, pub author: Author, pub change_id: Option, @@ -188,7 +186,7 @@ pub(crate) fn commit_to_remote_commit(commit: &git2::Commit) -> RemoteCommit { let parent_ids = commit.parents().map(|c| c.id()).collect(); RemoteCommit { id: commit.id().to_string(), - description: commit.message_bstr().to_owned(), + description: commit.message_bstr().into(), created_at: commit.time().seconds().try_into().unwrap(), author: commit.author().into(), change_id: commit.change_id(), diff --git a/crates/gitbutler-branch/Cargo.toml b/crates/gitbutler-branch/Cargo.toml index 8a76f02cd..76f46e935 100644 --- a/crates/gitbutler-branch/Cargo.toml +++ b/crates/gitbutler-branch/Cargo.toml @@ -8,7 +8,7 @@ publish = false [dependencies] anyhow = "1.0.86" git2.workspace = true -gix = { workspace = true, features = ["serde"] } +gix = { workspace = true, features = [] } gitbutler-reference.workspace = true gitbutler-serde.workspace = true gitbutler-id.workspace = true diff --git a/crates/gitbutler-branch/src/branch.rs b/crates/gitbutler-branch/src/branch.rs index 0e89850da..5a0b5bc43 100644 --- a/crates/gitbutler-branch/src/branch.rs +++ b/crates/gitbutler-branch/src/branch.rs @@ -1,8 +1,8 @@ use anyhow::Result; -use bstr::BStr; +use bstr::{BStr, ByteSlice}; use gitbutler_id::id::Id; use gitbutler_reference::{normalize_branch_name, Refname, RemoteRefname, VirtualRefname}; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize, Serializer}; use std::ops::Deref; use crate::ownership::BranchOwnershipClaims; @@ -146,12 +146,21 @@ pub struct BranchCreateRequest { /// or `feat/one` for `refs/remotes/my/special/remote/feat/one`. /// * For virtual branches, it's either the above if there is a `source_refname` or an `upstream`, or it's the normalized /// name of the virtual branch. -#[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash, Ord, PartialOrd)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] pub struct BranchIdentity( /// The identity is always a valid reference name, full or partial. pub gix::refs::PartialName, ); +impl Serialize for BranchIdentity { + fn serialize(&self, s: S) -> std::result::Result + where + S: Serializer, + { + self.0.as_ref().as_bstr().to_str_lossy().serialize(s) + } +} + impl Deref for BranchIdentity { type Target = BStr; diff --git a/crates/gitbutler-diff/src/diff.rs b/crates/gitbutler-diff/src/diff.rs index 8bad62d94..6585a5761 100644 --- a/crates/gitbutler-diff/src/diff.rs +++ b/crates/gitbutler-diff/src/diff.rs @@ -7,6 +7,7 @@ use std::{ use anyhow::{Context, Result}; use bstr::{BStr, BString, ByteSlice, ByteVec}; +use gitbutler_serde::BStringForFrontend; use serde::{Deserialize, Serialize}; use tracing::instrument; @@ -49,8 +50,8 @@ pub struct GitHunk { pub new_start: u32, pub new_lines: u32, /// The `+`, `-` or ` ` prefixed lines of the diff produced by `git2`, along with their line separator. - #[serde(rename = "diff", serialize_with = "gitbutler_serde::as_string_lossy")] - pub diff_lines: BString, + #[serde(rename = "diff")] + pub diff_lines: BStringForFrontend, pub binary: bool, pub change_type: ChangeType, } @@ -307,7 +308,7 @@ pub fn hunks_by_filepath( old_lines, new_start, new_lines, - diff_lines: line.into_owned(), + diff_lines: line.into_owned().into(), binary: false, change_type, } @@ -413,7 +414,7 @@ pub fn reverse_hunk(hunk: &GitHunk) -> Option { old_lines: hunk.new_lines, new_start: hunk.old_start, new_lines: hunk.old_lines, - diff_lines: diff, + diff_lines: diff.into(), binary: hunk.binary, change_type: hunk.change_type, }) diff --git a/crates/gitbutler-serde/src/bstring.rs b/crates/gitbutler-serde/src/bstring.rs new file mode 100644 index 000000000..86b982ab5 --- /dev/null +++ b/crates/gitbutler-serde/src/bstring.rs @@ -0,0 +1,72 @@ +use bstr::{BStr, BString, ByteSlice}; +use serde::{Serialize, Serializer}; +use std::ops::{Deref, DerefMut}; + +/// A form of `BString` for use in structures that are going to be serialized for the frontend as string. +/// +/// ### Note +/// +/// `BString` provides its own serialize implementation, but serializes as list of bytes, something that +/// would break the UI. Thus, whenever `BString` is involved, a custom serialization or this type +/// will be required. +#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Default)] +pub struct BStringForFrontend(BString); + +impl Serialize for BStringForFrontend { + fn serialize(&self, s: S) -> Result + where + S: Serializer, + { + self.0.to_str_lossy().serialize(s) + } +} + +impl Deref for BStringForFrontend { + type Target = BString; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for BStringForFrontend { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl AsRef<[u8]> for BStringForFrontend { + fn as_ref(&self) -> &[u8] { + self.0.as_ref() + } +} + +impl AsRef for BStringForFrontend { + fn as_ref(&self) -> &BStr { + self.0.as_ref() + } +} + +impl From for BStringForFrontend { + fn from(value: String) -> Self { + BStringForFrontend(value.into()) + } +} + +impl From for BStringForFrontend { + fn from(value: BString) -> Self { + BStringForFrontend(value) + } +} + +impl From<&BStr> for BStringForFrontend { + fn from(value: &BStr) -> Self { + BStringForFrontend(value.into()) + } +} + +impl PartialEq<&str> for BStringForFrontend { + fn eq(&self, other: &&str) -> bool { + self.0.eq(other) + } +} diff --git a/crates/gitbutler-serde/src/lib.rs b/crates/gitbutler-serde/src/lib.rs index 70a24cd27..9f1d3246a 100644 --- a/crates/gitbutler-serde/src/lib.rs +++ b/crates/gitbutler-serde/src/lib.rs @@ -1,20 +1,7 @@ -use bstr::{BString, ByteSlice}; use serde::Serialize; -pub fn as_string_lossy(v: &BString, s: S) -> Result -where - S: serde::Serializer, -{ - v.to_str_lossy().serialize(s) -} - -pub fn as_string_lossy_vec(v: &[BString], s: S) -> Result -where - S: serde::Serializer, -{ - let vec: Vec = v.iter().map(|v| v.to_string()).collect(); - vec.serialize(s) -} +mod bstring; +pub use bstring::BStringForFrontend; pub fn as_string_lossy_vec_remote_name( v: &[gix::remote::Name<'static>],