Skip to content

Commit 0fdde59

Browse files
committed
wip
1 parent a92fa17 commit 0fdde59

File tree

8 files changed

+133
-25
lines changed

8 files changed

+133
-25
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
use anyhow::{Context, Result};
2+
3+
use crate::types::ReferenceName;
4+
5+
pub trait BranchExt {
6+
fn reference_name(&self) -> Result<ReferenceName>;
7+
}
8+
9+
impl<'repo> BranchExt for git2::Branch<'repo> {
10+
fn reference_name(&self) -> Result<ReferenceName> {
11+
let name = self.get().name().context("Failed to get branch name")?;
12+
13+
Ok(name.into())
14+
}
15+
}

crates/gitbutler-core/src/git/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,6 @@ pub use commit_ext::*;
1818

1919
mod commit_buffer;
2020
pub use commit_buffer::*;
21+
22+
mod branch_ext;
23+
pub use branch_ext::*;

crates/gitbutler-core/src/types/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@ pub mod default_true;
88
pub struct Sensitive<T>(pub T);
99

1010
mod sensitive;
11+
12+
mod tagged_string;
13+
pub use tagged_string::*;
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
use std::{fmt, marker::PhantomData, ops::Deref};
2+
3+
use serde::{Deserialize, Deserializer, Serialize, Serializer};
4+
5+
/// Tagged string is designed to clarify the purpose of strings when used as a return type
6+
pub struct TaggedString<T>(String, PhantomData<T>);
7+
8+
impl<T> From<String> for TaggedString<T> {
9+
fn from(value: String) -> Self {
10+
TaggedString(value, PhantomData)
11+
}
12+
}
13+
14+
impl<T> From<&str> for TaggedString<T> {
15+
fn from(value: &str) -> Self {
16+
TaggedString(value.to_string(), PhantomData)
17+
}
18+
}
19+
20+
impl<T> Deref for TaggedString<T> {
21+
type Target = String;
22+
23+
fn deref(&self) -> &Self::Target {
24+
&self.0
25+
}
26+
}
27+
28+
impl<'de, T> Deserialize<'de> for TaggedString<T> {
29+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
30+
where
31+
D: Deserializer<'de>,
32+
{
33+
String::deserialize(deserializer).map(Into::into)
34+
}
35+
}
36+
37+
impl<T> Serialize for TaggedString<T> {
38+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
39+
where
40+
S: Serializer,
41+
{
42+
self.0.serialize(serializer)
43+
}
44+
}
45+
46+
impl<T> fmt::Display for TaggedString<T> {
47+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48+
self.0.fmt(f)
49+
}
50+
}
51+
52+
impl<T> fmt::Debug for TaggedString<T> {
53+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54+
self.0.fmt(f)
55+
}
56+
}
57+
58+
pub struct _ReferenceName;
59+
/// The name of a reference ie. `refs/heads/master`
60+
pub type ReferenceName = TaggedString<_ReferenceName>;

crates/gitbutler-core/src/virtual_branches/base.rs

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@ use git2::Index;
55
use serde::Serialize;
66

77
use super::{
8-
branch,
8+
branch, convert_to_real_branch,
99
integration::{
1010
get_workspace_head, update_gitbutler_integration, GITBUTLER_INTEGRATION_REFERENCE,
1111
},
1212
target, BranchId, RemoteCommit, VirtualBranchHunk, VirtualBranchesHandle,
1313
};
14-
use crate::{git::RepositoryExt, virtual_branches::errors::Marker};
14+
use crate::{
15+
git::BranchExt, git::RepositoryExt, types::ReferenceName, virtual_branches::errors::Marker,
16+
};
1517
use crate::{
1618
git::{self, diff},
1719
project_repository::{self, LogUntil},
@@ -327,10 +329,10 @@ fn _print_tree(repo: &git2::Repository, tree: &git2::Tree) -> Result<()> {
327329
// determine if what the target branch is now pointing to is mergeable with our current working directory
328330
// merge the target branch into our current working directory
329331
// update the target sha
330-
pub fn update_base_branch(
331-
project_repository: &project_repository::Repository,
332+
pub fn update_base_branch<'repo>(
333+
project_repository: &'repo project_repository::Repository,
332334
user: Option<&users::User>,
333-
) -> anyhow::Result<Vec<branch::Branch>> {
335+
) -> anyhow::Result<Vec<git2::Branch<'repo>>> {
334336
project_repository.assure_resolved()?;
335337

336338
// look up the target and see if there is a new oid
@@ -346,10 +348,10 @@ pub fn update_base_branch(
346348
.peel_to_commit()
347349
.context(format!("failed to peel branch {} to commit", target.branch))?;
348350

349-
let mut unapplied_branches: Vec<branch::Branch> = Vec::new();
351+
let mut unapplied_branch_names: Vec<git2::Branch> = Vec::new();
350352

351353
if new_target_commit.id() == target.sha {
352-
return Ok(unapplied_branches);
354+
return Ok(unapplied_branch_names);
353355
}
354356

355357
let new_target_tree = new_target_commit
@@ -423,11 +425,13 @@ pub fn update_base_branch(
423425

424426
if branch_tree_merge_index.has_conflicts() {
425427
// branch tree conflicts with new target, unapply branch for now. we'll handle it later, when user applies it back.
426-
if branch.applied {
427-
unapplied_branches.push(branch.clone());
428-
}
429-
branch.applied = false;
430-
vb_state.set_branch(branch.clone())?;
428+
let unapplied_real_branch = convert_to_real_branch(
429+
project_repository,
430+
branch.id,
431+
Default::default(),
432+
)?;
433+
unapplied_branch_names.push(unapplied_real_branch);
434+
431435
return Ok(Some(branch));
432436
}
433437

@@ -456,11 +460,13 @@ pub fn update_base_branch(
456460
if branch_head_merge_index.has_conflicts() {
457461
// branch commits conflict with new target, make sure the branch is
458462
// unapplied. conflicts witll be dealt with when applying it back.
459-
if branch.applied {
460-
unapplied_branches.push(branch.clone());
461-
}
462-
branch.applied = false;
463-
vb_state.set_branch(branch.clone())?;
463+
let unapplied_real_branch = convert_to_real_branch(
464+
project_repository,
465+
branch.id,
466+
Default::default(),
467+
)?;
468+
unapplied_branch_names.push(unapplied_real_branch);
469+
464470
return Ok(Some(branch));
465471
}
466472

@@ -567,7 +573,7 @@ pub fn update_base_branch(
567573

568574
// Rewriting the integration commit is necessary after changing target sha.
569575
super::integration::update_gitbutler_integration(&vb_state, project_repository)?;
570-
Ok(unapplied_branches)
576+
Ok(unapplied_branch_names)
571577
}
572578

573579
pub fn target_to_base_branch(

crates/gitbutler-core/src/virtual_branches/controller.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
use crate::ops::entry::{OperationKind, SnapshotDetails};
1+
use crate::{
2+
git::BranchExt,
3+
ops::entry::{OperationKind, SnapshotDetails},
4+
types::ReferenceName,
5+
};
26
use anyhow::Result;
37
use std::{collections::HashMap, path::Path, sync::Arc};
48

@@ -7,7 +11,7 @@ use tokio::{sync::Semaphore, task::JoinHandle};
711

812
use super::{
913
branch::{BranchId, BranchOwnershipClaims},
10-
target, target_to_base_branch, BaseBranch, Branch, NameConflitResolution, RemoteBranchFile,
14+
target, target_to_base_branch, BaseBranch, NameConflitResolution, RemoteBranchFile,
1115
VirtualBranchesHandle,
1216
};
1317
use crate::{
@@ -152,7 +156,7 @@ impl Controller {
152156
.await
153157
}
154158

155-
pub async fn update_base_branch(&self, project_id: ProjectId) -> Result<Vec<Branch>> {
159+
pub async fn update_base_branch(&self, project_id: ProjectId) -> Result<Vec<ReferenceName>> {
156160
self.inner(project_id)
157161
.await
158162
.update_base_branch(project_id)
@@ -551,14 +555,21 @@ impl ControllerInner {
551555
})
552556
}
553557

554-
pub async fn update_base_branch(&self, project_id: ProjectId) -> Result<Vec<Branch>> {
558+
pub async fn update_base_branch(&self, project_id: ProjectId) -> Result<Vec<ReferenceName>> {
555559
let _permit = self.semaphore.acquire().await;
556560

557561
self.with_verify_branch(project_id, |project_repository, user| {
558562
let _ = project_repository
559563
.project()
560564
.create_snapshot(SnapshotDetails::new(OperationKind::UpdateWorkspaceBase));
561-
super::update_base_branch(project_repository, user).map_err(Into::into)
565+
super::update_base_branch(project_repository, user)
566+
.map(|unapplied_branches| {
567+
unapplied_branches
568+
.iter()
569+
.filter_map(|unapplied_branch| unapplied_branch.reference_name().ok())
570+
.collect()
571+
})
572+
.map_err(Into::into)
562573
})
563574
}
564575

crates/gitbutler-core/tests/suite/virtual_branches/update_base_branch.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,15 @@ mod applied_branch {
796796
)
797797
.unwrap();
798798

799+
let branch_count = controller
800+
.list_virtual_branches(*project_id)
801+
.await
802+
.unwrap()
803+
.0
804+
.len();
805+
806+
println!("branch count: {}", branch_count);
807+
799808
{
800809
// merge branch remotely
801810
let branch = controller
@@ -810,7 +819,7 @@ mod applied_branch {
810819
repository.fetch();
811820

812821
{
813-
controller.update_base_branch(*project_id).await.unwrap();
822+
dbg!(controller.update_base_branch(*project_id).await.unwrap());
814823

815824
// removes integrated commit, leaves non commited work as is
816825

crates/gitbutler-tauri/src/virtual_branches.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ pub mod commands {
66
error::Code,
77
git,
88
projects::{self, ProjectId},
9+
types::ReferenceName,
910
virtual_branches::{
1011
branch::{self, BranchId, BranchOwnershipClaims},
1112
controller::Controller,
@@ -154,7 +155,7 @@ pub mod commands {
154155
pub async fn update_base_branch(
155156
handle: AppHandle,
156157
project_id: ProjectId,
157-
) -> Result<Vec<branch::Branch>, Error> {
158+
) -> Result<Vec<ReferenceName>, Error> {
158159
let unapplied_branches = handle
159160
.state::<Controller>()
160161
.update_base_branch(project_id)

0 commit comments

Comments
 (0)