Skip to content

Commit 4c76e2a

Browse files
committed
Revert "Revert "Merge pull request gitbutlerapp#4652 from gitbutlerapp/git2-to-gix""
This reverts commit 88496e6.
1 parent eebdae6 commit 4c76e2a

File tree

28 files changed

+532
-410
lines changed

28 files changed

+532
-410
lines changed

Cargo.lock

Lines changed: 292 additions & 195 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@ members = [
3333
resolver = "2"
3434

3535
[workspace.dependencies]
36+
bstr = { version = "1.10.0", features = ["serde"] }
3637
# Add the `tracing` or `tracing-detail` features to see more of gitoxide in the logs. Useful to see which programs it invokes.
37-
gix = { git = "https://github.com/Byron/gitoxide", rev = "29898e3010bd3332418c683f2ac96aff5c8e72fa", default-features = false, features = [] }
38+
gix = { git = "https://github.com/Byron/gitoxide", rev = "7dff44754e0fdc369f92221468fb953bad9be60a", default-features = false, features = ["serde"] }
3839
git2 = { version = "0.18.3", features = [
3940
"vendored-openssl",
4041
"vendored-libgit2",

crates/gitbutler-branch-actions/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ gitbutler-fs.workspace = true
2626
gitbutler-diff.workspace = true
2727
gitbutler-operating-modes.workspace = true
2828
serde = { workspace = true, features = ["std"] }
29-
bstr = "1.10.0"
29+
bstr.workspace = true
3030
diffy = "0.4.0"
3131
hex = "0.4.3"
3232
regex = "1.10"

crates/gitbutler-branch-actions/src/base.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ pub struct BaseBranch {
3131
pub remote_url: String,
3232
pub push_remote_name: Option<String>,
3333
pub push_remote_url: String,
34-
#[serde(with = "gitbutler_serde::serde::oid")]
34+
#[serde(with = "gitbutler_serde::oid")]
3535
pub base_sha: git2::Oid,
36-
#[serde(with = "gitbutler_serde::serde::oid")]
36+
#[serde(with = "gitbutler_serde::oid")]
3737
pub current_sha: git2::Oid,
3838
pub behind: usize,
3939
pub upstream_commits: Vec<RemoteCommit>,

crates/gitbutler-branch-actions/src/branch.rs

Lines changed: 46 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ use crate::VirtualBranchesExt;
22
use anyhow::{Context, Result};
33
use bstr::{BStr, BString, ByteSlice};
44
use core::fmt;
5-
use gitbutler_branch::{Branch as GitButlerBranch, BranchId, ReferenceExtGix, Target};
5+
use gitbutler_branch::{
6+
Branch as GitButlerBranch, BranchId, BranchIdentity, ReferenceExtGix, Target,
7+
};
68
use gitbutler_command_context::CommandContext;
79
use gitbutler_reference::normalize_branch_name;
810
use gix::prelude::ObjectIdExt;
@@ -33,9 +35,12 @@ pub fn list_branches(
3335
for reference in platform.all()?.filter_map(Result::ok) {
3436
// Loosely match on branch names
3537
if let Some(branch_names) = &filter_branch_names {
36-
let has_matching_name = branch_names
37-
.iter()
38-
.any(|branch_name| reference.name().as_bstr().ends_with_str(&branch_name.0));
38+
let has_matching_name = branch_names.iter().any(|branch_name| {
39+
reference
40+
.name()
41+
.as_bstr()
42+
.ends_with_str(branch_name.as_bstr())
43+
});
3944

4045
if !has_matching_name {
4146
continue;
@@ -189,9 +194,13 @@ fn branch_group_to_branch(
189194
};
190195

191196
if virtual_branch.is_none()
192-
&& local_branches
193-
.iter()
194-
.any(|b| b.name().given_name(remotes).as_deref().ok() == Some(target.branch.branch()))
197+
&& local_branches.iter().any(|b| {
198+
b.name()
199+
.identity(remotes)
200+
.as_deref()
201+
.ok()
202+
.map_or(false, |identity| identity == target.branch.branch())
203+
})
195204
{
196205
return Ok(None);
197206
}
@@ -203,11 +212,10 @@ fn branch_group_to_branch(
203212
in_workspace: branch.in_workspace,
204213
});
205214

206-
// TODO(ST): keep the type alive, don't reduce to BString
207-
let mut remotes: Vec<BString> = Vec::new();
215+
let mut remotes: Vec<gix::remote::Name<'static>> = Vec::new();
208216
for branch in remote_branches.iter() {
209217
if let Some(remote_name) = branch.remote_name(gix::remote::Direction::Fetch) {
210-
remotes.push(remote_name.as_bstr().into());
218+
remotes.push(remote_name.to_owned());
211219
}
212220
}
213221

@@ -293,7 +301,7 @@ impl GroupBranch<'_> {
293301
fn identity(&self, remotes: &BTreeSet<Cow<'_, BStr>>) -> Option<BranchIdentity> {
294302
match self {
295303
GroupBranch::Local(branch) | GroupBranch::Remote(branch) => {
296-
branch.name().given_name(remotes).ok()
304+
branch.name().identity(remotes).ok()
297305
}
298306
// The identity of a Virtual branch is derived from the source refname, upstream or the branch given name, in that order
299307
GroupBranch::Virtual(branch) => {
@@ -302,25 +310,24 @@ impl GroupBranch<'_> {
302310
let rich_name = branch.name.clone();
303311
let rich_name = normalize_branch_name(&rich_name).ok()?;
304312
let identity = name_from_source.unwrap_or(name_from_upstream.unwrap_or(&rich_name));
305-
Some(identity.to_string())
313+
Some(identity.into())
306314
}
307315
}
308-
.map(BranchIdentity)
316+
.map(BranchIdentity::from)
309317
}
310318
}
311319

312320
/// Determines if a branch should be listed in the UI.
313321
/// This excludes the target branch as well as gitbutler specific branches.
314322
fn should_list_git_branch(identity: &BranchIdentity) -> bool {
315323
// Exclude gitbutler technical branches (not useful for the user)
316-
let is_technical = [
317-
"gitbutler/integration",
318-
"gitbutler/target",
319-
"gitbutler/oplog",
320-
"HEAD",
321-
]
322-
.contains(&&*identity.0);
323-
!is_technical
324+
const TECHNICAL_IDENTITIES: &[&[u8]] = &[
325+
b"gitbutler/integration",
326+
b"gitbutler/target",
327+
b"gitbutler/oplog",
328+
b"HEAD",
329+
];
330+
!TECHNICAL_IDENTITIES.contains(&identity.as_bytes())
324331
}
325332

326333
/// A filter that can be applied to the branch listing
@@ -347,8 +354,8 @@ pub struct BranchListing {
347354
pub name: BranchIdentity,
348355
/// This is a list of remotes that this branch can be found on (e.g. `origin`, `upstream` etc.),
349356
/// by collecting remotes from all local branches with the same identity that have a tracking setup.
350-
#[serde(serialize_with = "gitbutler_serde::serde::as_string_lossy_vec")]
351-
pub remotes: Vec<BString>,
357+
#[serde(serialize_with = "gitbutler_serde::as_string_lossy_vec_remote_name")]
358+
pub remotes: Vec<gix::remote::Name<'static>>,
352359
/// The branch may or may not have a virtual branch associated with it.
353360
pub virtual_branch: Option<VirtualBranchReference>,
354361
/// Timestamp in milliseconds since the branch was last updated.
@@ -370,52 +377,25 @@ pub struct BranchListing {
370377
/// Represents a "commit author" or "signature", based on the data from the git history
371378
#[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)]
372379
pub struct Author {
373-
// TODO(ST): use `BString` here to not degenerate information
374380
/// The name of the author as configured in the git config
375-
pub name: Option<String>,
381+
pub name: Option<BString>,
376382
/// The email of the author as configured in the git config
377-
pub email: Option<String>,
378-
}
379-
380-
/// The identity of a branch as to allow to group similar branches together.
381-
///
382-
/// * For *local* branches, it is what's left without the standard prefix, like `refs/heads`, e.g. `main`
383-
/// for `refs/heads/main` or `feat/one` for `refs/heads/feat/one`.
384-
/// * For *remote* branches, it is what's without the prefix and remote name, like `main` for `refs/remotes/origin/main`.
385-
/// or `feat/one` for `refs/remotes/my/special/remote/feat/one`.
386-
/// * For virtual branches, it's either the above if there is a `source_refname` or an `upstream`, or it's the normalized
387-
/// name of the virtual branch.
388-
#[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash, Ord, PartialOrd)]
389-
pub struct BranchIdentity(String);
390-
391-
/// Facilitate obtaining this type from the UI - otherwise it would be better not to have it as it should be
392-
/// a particular thing, not any string.
393-
impl From<String> for BranchIdentity {
394-
fn from(value: String) -> Self {
395-
BranchIdentity(value)
396-
}
397-
}
398-
399-
/// Also not for testing.
400-
impl From<&str> for BranchIdentity {
401-
fn from(value: &str) -> Self {
402-
BranchIdentity(value.into())
403-
}
383+
pub email: Option<BString>,
404384
}
405385

406386
impl From<git2::Signature<'_>> for Author {
407387
fn from(value: git2::Signature) -> Self {
408-
let name = value.name().map(str::to_string);
409-
let email = value.email().map(str::to_string);
388+
let name = value.name().map(str::to_string).map(Into::into);
389+
let email = value.email().map(str::to_string).map(Into::into);
410390
Author { name, email }
411391
}
412392
}
413393

414394
impl From<gix::actor::SignatureRef<'_>> for Author {
415395
fn from(value: gix::actor::SignatureRef<'_>) -> Self {
416396
Author {
417-
name: Some(value.name.to_string()),
418-
email: Some(value.email.to_string()),
397+
name: Some(value.name.to_owned()),
398+
email: Some(value.email.to_owned()),
419399
}
420400
}
421401
}
@@ -436,9 +416,13 @@ pub struct VirtualBranchReference {
436416
/// a list of enriched branch data in the form of `BranchData`.
437417
pub fn get_branch_listing_details(
438418
ctx: &CommandContext,
439-
branch_names: impl IntoIterator<Item = impl Into<BranchIdentity>>,
419+
branch_names: impl IntoIterator<Item = impl TryInto<BranchIdentity>>,
440420
) -> Result<Vec<BranchListingDetails>> {
441-
let branch_names: Vec<_> = branch_names.into_iter().map(Into::into).collect();
421+
let branch_names: Vec<_> = branch_names
422+
.into_iter()
423+
.map(TryInto::try_into)
424+
.filter_map(Result::ok)
425+
.collect();
442426
let repo = ctx.repository();
443427
let branches = list_branches(ctx, None, Some(branch_names.clone()))?;
444428
let default_target = ctx
@@ -536,10 +520,10 @@ pub struct BranchEntry {
536520
/// The name of the branch (e.g. `main`, `feature/branch`)
537521
pub name: String,
538522
/// The head commit of the branch
539-
#[serde(with = "gitbutler_serde::serde::oid")]
523+
#[serde(with = "gitbutler_serde::oid")]
540524
head: git2::Oid,
541525
/// The commit base of the branch
542-
#[serde(with = "gitbutler_serde::serde::oid")]
526+
#[serde(with = "gitbutler_serde::oid")]
543527
base: git2::Oid,
544528
/// The list of commits associated with the branch
545529
pub commits: Vec<CommitEntry>,
@@ -568,18 +552,17 @@ pub struct RemoteBranchEntry {
568552
#[serde(rename_all = "camelCase")]
569553
pub struct CommitEntry {
570554
/// The commit sha that it can be referenced by
571-
#[serde(with = "gitbutler_serde::serde::oid")]
555+
#[serde(with = "gitbutler_serde::oid")]
572556
pub id: git2::Oid,
573557
/// If the commit is referencing a specific change, this is its change id
574558
pub change_id: Option<String>,
575559
/// The commit message
576-
#[serde(serialize_with = "gitbutler_serde::serde::as_string_lossy")]
577560
pub description: BString,
578561
/// The timestamp of the commit in milliseconds
579562
pub created_at: u128,
580563
/// The author of the commit
581564
pub authors: Vec<Author>,
582565
/// The parent commits of the commit
583-
#[serde(with = "gitbutler_serde::serde::oid_vec")]
566+
#[serde(with = "gitbutler_serde::oid_vec")]
584567
pub parent_ids: Vec<git2::Oid>,
585568
}

crates/gitbutler-branch-actions/src/commit.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,15 @@ use crate::{
2121
#[derive(Debug, PartialEq, Clone, Serialize)]
2222
#[serde(rename_all = "camelCase")]
2323
pub struct VirtualBranchCommit {
24-
#[serde(with = "gitbutler_serde::serde::oid")]
24+
#[serde(with = "gitbutler_serde::oid")]
2525
pub id: git2::Oid,
26-
#[serde(serialize_with = "gitbutler_serde::serde::as_string_lossy")]
2726
pub description: BString,
2827
pub created_at: u128,
2928
pub author: Author,
3029
pub is_remote: bool,
3130
pub files: Vec<VirtualBranchFile>,
3231
pub is_integrated: bool,
33-
#[serde(with = "gitbutler_serde::serde::oid_vec")]
32+
#[serde(with = "gitbutler_serde::oid_vec")]
3433
pub parent_ids: Vec<git2::Oid>,
3534
pub branch_id: BranchId,
3635
pub change_id: Option<String>,

crates/gitbutler-branch-actions/src/hunk.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ use serde::Serialize;
2424
#[serde(rename_all = "camelCase")]
2525
pub struct VirtualBranchHunk {
2626
pub id: String,
27-
#[serde(serialize_with = "gitbutler_serde::serde::as_string_lossy")]
2827
pub diff: BString,
2928
pub modified_at: u128,
3029
pub file_path: PathBuf,
@@ -50,7 +49,7 @@ pub struct VirtualBranchHunk {
5049
#[serde(rename_all = "camelCase")]
5150
pub struct HunkLock {
5251
pub branch_id: BranchId,
53-
#[serde(with = "gitbutler_serde::serde::oid")]
52+
#[serde(with = "gitbutler_serde::oid")]
5453
pub commit_id: git2::Oid,
5554
}
5655

crates/gitbutler-branch-actions/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,6 @@ mod commit;
4141
mod hunk;
4242

4343
pub use branch::{
44-
get_branch_listing_details, list_branches, Author, BranchIdentity, BranchListing,
45-
BranchListingDetails, BranchListingFilter,
44+
get_branch_listing_details, list_branches, Author, BranchListing, BranchListingDetails,
45+
BranchListingFilter,
4646
};

crates/gitbutler-branch-actions/src/remote.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use crate::author::Author;
2323
#[derive(Debug, Clone, Serialize, PartialEq)]
2424
#[serde(rename_all = "camelCase")]
2525
pub struct RemoteBranch {
26-
#[serde(with = "gitbutler_serde::serde::oid")]
26+
#[serde(with = "gitbutler_serde::oid")]
2727
pub sha: git2::Oid,
2828
pub name: Refname,
2929
pub upstream: Option<RemoteRefname>,
@@ -36,26 +36,25 @@ pub struct RemoteBranch {
3636
#[derive(Debug, Clone, Serialize, PartialEq)]
3737
#[serde(rename_all = "camelCase")]
3838
pub struct RemoteBranchData {
39-
#[serde(with = "gitbutler_serde::serde::oid")]
39+
#[serde(with = "gitbutler_serde::oid")]
4040
pub sha: git2::Oid,
4141
pub name: Refname,
4242
pub upstream: Option<RemoteRefname>,
4343
pub behind: u32,
4444
pub commits: Vec<RemoteCommit>,
45-
#[serde(with = "gitbutler_serde::serde::oid_opt", default)]
45+
#[serde(with = "gitbutler_serde::oid_opt", default)]
4646
pub fork_point: Option<git2::Oid>,
4747
}
4848

4949
#[derive(Debug, Clone, PartialEq, Serialize)]
5050
#[serde(rename_all = "camelCase")]
5151
pub struct RemoteCommit {
5252
pub id: String,
53-
#[serde(serialize_with = "gitbutler_serde::serde::as_string_lossy")]
5453
pub description: BString,
5554
pub created_at: u128,
5655
pub author: Author,
5756
pub change_id: Option<String>,
58-
#[serde(with = "gitbutler_serde::serde::oid_vec")]
57+
#[serde(with = "gitbutler_serde::oid_vec")]
5958
pub parent_ids: Vec<git2::Oid>,
6059
}
6160

crates/gitbutler-branch-actions/src/virtual.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,13 @@ pub struct VirtualBranch {
6868
pub updated_at: u128,
6969
pub selected_for_changes: bool,
7070
pub allow_rebasing: bool,
71-
#[serde(with = "gitbutler_serde::serde::oid")]
71+
#[serde(with = "gitbutler_serde::oid")]
7272
pub head: git2::Oid,
7373
/// The merge base between the target branch and the virtual branch
74-
#[serde(with = "gitbutler_serde::serde::oid")]
74+
#[serde(with = "gitbutler_serde::oid")]
7575
pub merge_base: git2::Oid,
7676
/// The fork point between the target branch and the virtual branch
77-
#[serde(with = "gitbutler_serde::serde::oid_opt", default)]
77+
#[serde(with = "gitbutler_serde::oid_opt", default)]
7878
pub fork_point: Option<git2::Oid>,
7979
}
8080

0 commit comments

Comments
 (0)