ensure branch updated time is always up to date

This commit is contained in:
Nikita Galaiko 2023-12-13 15:25:01 +01:00 committed by GitButler
parent 82b861758c
commit 0cdf187115
11 changed files with 264 additions and 306 deletions

View File

@ -288,10 +288,8 @@ impl Repository {
// copy branches that we don't already have
for branch in &branches {
let branch_copy = branch.clone();
//branch_copy.applied = false;
dst_branch_writer
.write(&branch_copy)
.write(&mut branch.clone())
.with_context(|| format!("{}: failed to write branch", branch.id))?;
}

View File

@ -176,7 +176,7 @@ pub fn set_base_branch(
(None, None)
};
let branch = branch::Branch {
let mut branch = branch::Branch {
id: BranchId::generate(),
name: head_name.to_string().replace("refs/heads/", ""),
notes: String::new(),
@ -196,7 +196,7 @@ pub fn set_base_branch(
};
let branch_writer = branch::Writer::new(gb_repository);
branch_writer.write(&branch)?;
branch_writer.write(&mut branch)?;
}
}
@ -294,106 +294,174 @@ pub fn update_base_branch(
let updated_vbranches = super::get_status_by_branch(gb_repository, project_repository)?
.into_iter()
.map(|(branch, _)| branch)
.map(|branch: branch::Branch| -> Result<Option<branch::Branch>> {
let branch_tree = repo.find_tree(branch.tree)?;
.map(
|mut branch: branch::Branch| -> Result<Option<branch::Branch>> {
let branch_tree = repo.find_tree(branch.tree)?;
let mut branch_merge_index = repo
.merge_trees(&old_target_tree, &branch_tree, &new_target_tree)
.context(format!("failed to merge trees for branch {}", branch.id))?;
let mut branch_merge_index = repo
.merge_trees(&old_target_tree, &branch_tree, &new_target_tree)
.context(format!("failed to merge trees for branch {}", branch.id))?;
if branch_merge_index.has_conflicts() {
// branch tree conflicts with new target, unapply branch for now. we'll handle it later, when user applies it back.
let branch = branch::Branch {
applied: false,
..branch
};
branch_writer.write(&branch)?;
return Ok(Some(branch));
}
if branch_merge_index.has_conflicts() {
// branch tree conflicts with new target, unapply branch for now. we'll handle it later, when user applies it back.
branch.applied = false;
branch_writer.write(&mut branch)?;
return Ok(Some(branch));
}
if branch.head == target.sha {
// there are no commits on the branch, so we can just update the head to the new target and calculate the new tree
let branch = branch::Branch {
head: new_target_commit.id(),
tree: branch_merge_index.write_tree_to(repo)?,
..branch
};
branch_writer.write(&branch)?;
return Ok(Some(branch));
}
if branch.head == target.sha {
// there are no commits on the branch, so we can just update the head to the new target and calculate the new tree
branch.head = new_target_commit.id();
branch.tree = branch_merge_index.write_tree_to(repo)?;
branch_writer.write(&mut branch)?;
return Ok(Some(branch));
}
// try to merge branch head with new target
let branch_head_commit = repo.find_commit(branch.head).context(format!(
"failed to find commit {} for branch {}",
branch.head, branch.id
))?;
let branch_head_tree = branch_head_commit.tree().context(format!(
"failed to find tree for commit {} for branch {}",
branch.head, branch.id
))?;
let mut branch_head_merge_index = repo
.merge_trees(&old_target_tree, &branch_head_tree, &new_target_tree)
.context(format!(
"failed to merge head tree for branch {}",
branch.id
// try to merge branch head with new target
let branch_head_commit = repo.find_commit(branch.head).context(format!(
"failed to find commit {} for branch {}",
branch.head, branch.id
))?;
let branch_head_tree = branch_head_commit.tree().context(format!(
"failed to find tree for commit {} for branch {}",
branch.head, branch.id
))?;
let mut branch_head_merge_index = repo
.merge_trees(&old_target_tree, &branch_head_tree, &new_target_tree)
.context(format!(
"failed to merge head tree for branch {}",
branch.id
))?;
if branch_head_merge_index.has_conflicts() {
// branch commits conflict with new target, make sure the branch is
// unapplied. conflicts witll be dealt with when applying it back.
let branch = branch::Branch {
applied: false,
..branch
};
branch_writer.write(&branch)?;
return Ok(Some(branch));
}
if branch_head_merge_index.has_conflicts() {
// branch commits conflict with new target, make sure the branch is
// unapplied. conflicts witll be dealt with when applying it back.
branch.applied = false;
branch_writer.write(&mut branch)?;
return Ok(Some(branch));
}
// branch commits do not conflict with new target, so lets merge them
let branch_head_merge_tree_oid =
branch_head_merge_index
// branch commits do not conflict with new target, so lets merge them
let branch_head_merge_tree_oid = branch_head_merge_index
.write_tree_to(repo)
.context(format!(
"failed to write head merge index for {}",
branch.id
))?;
if branch_head_merge_tree_oid == new_target_tree.id() {
// after merging the branch head with the new target the tree is the
// same as the new target tree. meaning we can safely use the new target commit
// as the new branch head.
let non_commited_files = diff::trees(
&project_repository.git_repository,
&branch_head_tree,
&branch_tree,
)?;
if non_commited_files.is_empty() {
// if there are no commited files, then the branch is fully merged
// and we can delete it.
branch_writer.delete(&branch)?;
project_repository.delete_branch_reference(&branch)?;
return Ok(None);
if branch_head_merge_tree_oid == new_target_tree.id() {
// after merging the branch head with the new target the tree is the
// same as the new target tree. meaning we can safely use the new target commit
// as the new branch head.
let non_commited_files = diff::trees(
&project_repository.git_repository,
&branch_head_tree,
&branch_tree,
)?;
if non_commited_files.is_empty() {
// if there are no commited files, then the branch is fully merged
// and we can delete it.
branch_writer.delete(&branch)?;
project_repository.delete_branch_reference(&branch)?;
return Ok(None);
}
// there are some uncommied files left. we should put them into the branch
// tree.
branch.head = new_target_commit.id();
branch.tree = branch_merge_index.write_tree_to(repo)?;
branch_writer.write(&mut branch)?;
return Ok(Some(branch));
}
// there are some uncommied files left. we should put them into the branch
// tree.
let branch = branch::Branch {
head: new_target_commit.id(),
tree: branch_merge_index.write_tree_to(repo)?,
..branch
};
branch_writer.write(&branch)?;
return Ok(Some(branch));
}
let ok_with_force_push = project_repository.project().ok_with_force_push;
if branch.upstream.is_some() && !ok_with_force_push {
// branch was pushed to upstream, and user doesn't like force pushing.
// create a merge commit to avoid the need of force pushing then.
let branch_head_merge_tree = repo
let ok_with_force_push = project_repository.project().ok_with_force_push;
if branch.upstream.is_some() && !ok_with_force_push {
// branch was pushed to upstream, and user doesn't like force pushing.
// create a merge commit to avoid the need of force pushing then.
let branch_head_merge_tree = repo
.find_tree(branch_head_merge_tree_oid)
.context("failed to find tree")?;
let new_target_head = project_repository
.commit(
user,
format!(
"Merged {}/{} into {}",
target.branch.remote(),
target.branch.branch(),
branch.name
)
.as_str(),
&branch_head_merge_tree,
&[&branch_head_commit, &new_target_commit],
signing_key,
)
.context("failed to commit merge")?;
branch.head = new_target_head;
branch.tree = branch_merge_index.write_tree_to(repo)?;
branch_writer.write(&mut branch)?;
return Ok(Some(branch));
}
// branch was not pushed to upstream yet. attempt a rebase,
let (_, committer) = project_repository.git_signatures(user)?;
let annotated_branch_head = repo
.find_annotated_commit(branch.head)
.context("failed to find annotated commit")?;
let annotated_upstream_base = repo
.find_annotated_commit(new_target_commit.id())
.context("failed to find annotated commit")?;
let mut rebase_options = git2::RebaseOptions::new();
rebase_options.quiet(true);
rebase_options.inmemory(true);
let mut rebase = repo
.rebase(
Some(&annotated_branch_head),
Some(&annotated_upstream_base),
None,
Some(&mut rebase_options),
)
.context("failed to rebase")?;
let mut rebase_success = true;
// check to see if these commits have already been pushed
let mut last_rebase_head = branch.head;
while rebase.next().is_some() {
let index = rebase
.inmemory_index()
.context("failed to get inmemory index")?;
if index.has_conflicts() {
rebase_success = false;
break;
}
if let Ok(commit_id) = rebase.commit(None, &committer.clone().into(), None) {
last_rebase_head = commit_id.into();
} else {
rebase_success = false;
break;
}
}
if rebase_success {
// rebase worked out, rewrite the branch head
rebase.finish(None).context("failed to finish rebase")?;
branch.head = last_rebase_head;
branch.tree = branch_merge_index.write_tree_to(repo)?;
branch_writer.write(&mut branch)?;
return Ok(Some(branch));
}
// rebase failed, do a merge commit
rebase.abort().context("failed to abort rebase")?;
// get tree from merge_tree_oid
let merge_tree = repo
.find_tree(branch_head_merge_tree_oid)
.context("failed to find tree")?;
let new_target_head = project_repository
// commit the merge tree oid
let new_branch_head = project_repository
.commit(
user,
format!(
@ -403,106 +471,18 @@ pub fn update_base_branch(
branch.name
)
.as_str(),
&branch_head_merge_tree,
&merge_tree,
&[&branch_head_commit, &new_target_commit],
signing_key,
)
.context("failed to commit merge")?;
let branch = branch::Branch {
head: new_target_head,
tree: branch_merge_index.write_tree_to(repo)?,
..branch
};
branch_writer.write(&branch)?;
return Ok(Some(branch));
}
// branch was not pushed to upstream yet. attempt a rebase,
let (_, committer) = project_repository.git_signatures(user)?;
let annotated_branch_head = repo
.find_annotated_commit(branch.head)
.context("failed to find annotated commit")?;
let annotated_upstream_base = repo
.find_annotated_commit(new_target_commit.id())
.context("failed to find annotated commit")?;
let mut rebase_options = git2::RebaseOptions::new();
rebase_options.quiet(true);
rebase_options.inmemory(true);
let mut rebase = repo
.rebase(
Some(&annotated_branch_head),
Some(&annotated_upstream_base),
None,
Some(&mut rebase_options),
)
.context("failed to rebase")?;
let mut rebase_success = true;
// check to see if these commits have already been pushed
let mut last_rebase_head = branch.head;
while rebase.next().is_some() {
let index = rebase
.inmemory_index()
.context("failed to get inmemory index")?;
if index.has_conflicts() {
rebase_success = false;
break;
}
if let Ok(commit_id) = rebase.commit(None, &committer.clone().into(), None) {
last_rebase_head = commit_id.into();
} else {
rebase_success = false;
break;
}
}
if rebase_success {
// rebase worked out, rewrite the branch head
rebase.finish(None).context("failed to finish rebase")?;
let branch = branch::Branch {
head: last_rebase_head,
tree: branch_merge_index.write_tree_to(repo)?,
..branch
};
branch_writer.write(&branch)?;
return Ok(Some(branch));
}
// rebase failed, do a merge commit
rebase.abort().context("failed to abort rebase")?;
// get tree from merge_tree_oid
let merge_tree = repo
.find_tree(branch_head_merge_tree_oid)
.context("failed to find tree")?;
// commit the merge tree oid
let new_branch_head = project_repository
.commit(
user,
format!(
"Merged {}/{} into {}",
target.branch.remote(),
target.branch.branch(),
branch.name
)
.as_str(),
&merge_tree,
&[&branch_head_commit, &new_target_commit],
signing_key,
)
.context("failed to commit merge")?;
let branch = branch::Branch {
head: new_branch_head,
tree: branch_merge_index.write_tree_to(repo)?,
..branch
};
branch_writer.write(&branch)?;
Ok(Some(branch))
})
branch.head = new_branch_head;
branch.tree = branch_merge_index.write_tree_to(repo)?;
branch_writer.write(&mut branch)?;
Ok(Some(branch))
},
)
.collect::<Result<Vec<_>>>()?
.into_iter()
.flatten()
@ -733,7 +713,9 @@ pub fn create_virtual_branch_from_branch(
}
let writer = branch::Writer::new(gb_repository);
writer.write(&branch).context("failed to write branch")?;
writer
.write(&mut branch)
.context("failed to write branch")?;
project_repository.add_branch_reference(&branch)?;

View File

@ -114,10 +114,10 @@ mod tests {
fn test_read_override() -> Result<()> {
let Case { gb_repository, .. } = Suite::default().new_case();
let branch = test_branch();
let mut branch = test_branch();
let writer = Writer::new(&gb_repository);
writer.write(&branch)?;
writer.write(&mut branch)?;
let session = gb_repository.get_current_session()?.unwrap();
let session_reader = sessions::Reader::open(&gb_repository, &session)?;

View File

@ -28,11 +28,15 @@ impl<'writer> BranchWriter<'writer> {
Ok(())
}
pub fn write(&self, branch: &Branch) -> Result<()> {
pub fn write(&self, branch: &mut Branch) -> Result<()> {
self.repository.mark_active_session()?;
let _lock = self.repository.lock();
branch.updated_timestamp_ms = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)?
.as_millis();
self.writer
.write_string(
&format!("branches/{}/id", branch.id),
@ -175,10 +179,10 @@ mod tests {
fn test_write_branch() -> Result<()> {
let Case { gb_repository, .. } = Suite::default().new_case();
let branch = test_branch();
let mut branch = test_branch();
let writer = BranchWriter::new(&gb_repository);
writer.write(&branch)?;
writer.write(&mut branch)?;
let root = gb_repository
.root()
@ -236,10 +240,10 @@ mod tests {
fn test_should_create_session() -> Result<()> {
let Case { gb_repository, .. } = Suite::default().new_case();
let branch = test_branch();
let mut branch = test_branch();
let writer = BranchWriter::new(&gb_repository);
writer.write(&branch)?;
writer.write(&mut branch)?;
assert!(gb_repository.get_current_session()?.is_some());
@ -250,12 +254,12 @@ mod tests {
fn test_should_update() -> Result<()> {
let Case { gb_repository, .. } = Suite::default().new_case();
let branch = test_branch();
let mut branch = test_branch();
let writer = BranchWriter::new(&gb_repository);
writer.write(&branch)?;
writer.write(&mut branch)?;
let updated_branch = Branch {
let mut updated_branch = Branch {
name: "updated_name".to_string(),
applied: false,
upstream: Some("refs/remotes/origin/upstream_updated".parse().unwrap()),
@ -265,7 +269,7 @@ mod tests {
..branch.clone()
};
writer.write(&updated_branch)?;
writer.write(&mut updated_branch)?;
let root = gb_repository
.root()

View File

@ -247,7 +247,7 @@ fn verify_head_is_clean(
)
.context("failed to reset to integration commit")?;
let new_branch = super::create_virtual_branch(
let mut new_branch = super::create_virtual_branch(
gb_repository,
project_repository,
&BranchCreateRequest {
@ -294,12 +294,10 @@ fn verify_head_is_clean(
rebased_commit_oid
))?;
new_branch.head = rebased_commit.id();
new_branch.tree = rebased_commit.tree_id();
writer
.write(&super::Branch {
head: rebased_commit.id(),
tree: rebased_commit.tree_id(),
..new_branch.clone()
})
.write(&mut new_branch)
.context("failed to write branch")?;
head = rebased_commit.id();

View File

@ -152,12 +152,12 @@ mod tests {
target_writer.write_default(&test_target())?;
let branch_writer = branch::Writer::new(&gb_repository);
let branch_1 = test_branch();
branch_writer.write(&branch_1)?;
let branch_2 = test_branch();
branch_writer.write(&branch_2)?;
let branch_3 = test_branch();
branch_writer.write(&branch_3)?;
let mut branch_1 = test_branch();
branch_writer.write(&mut branch_1)?;
let mut branch_2 = test_branch();
branch_writer.write(&mut branch_2)?;
let mut branch_3 = test_branch();
branch_writer.write(&mut branch_3)?;
let session = gb_repository.get_current_session()?.unwrap();
let session_reader = sessions::Reader::open(&gb_repository, &session)?;

View File

@ -157,7 +157,7 @@ mod tests {
fn test_read_override_target() -> Result<()> {
let Case { gb_repository, .. } = Suite::default().new_case();
let branch = test_branch();
let mut branch = test_branch();
let target = Target {
branch: "refs/remotes/remote/branch".parse().unwrap(),
@ -176,7 +176,7 @@ mod tests {
};
let branch_writer = branch::Writer::new(&gb_repository);
branch_writer.write(&branch)?;
branch_writer.write(&mut branch)?;
let session = gb_repository.get_current_session()?.unwrap();
let session_reader = sessions::Reader::open(&gb_repository, &session)?;

View File

@ -165,7 +165,7 @@ mod tests {
fn test_write() -> Result<()> {
let Case { gb_repository, .. } = Suite::default().new_case();
let branch = test_branch();
let mut branch = test_branch();
let target = Target {
branch: "refs/remotes/remote name/branch name".parse().unwrap(),
remote_url: "remote url".to_string(),
@ -174,7 +174,7 @@ mod tests {
};
let branch_writer = branch::Writer::new(&gb_repository);
branch_writer.write(&branch)?;
branch_writer.write(&mut branch)?;
let target_writer = TargetWriter::new(&gb_repository);
target_writer.write(&branch.id, &target)?;
@ -263,7 +263,7 @@ mod tests {
fn test_should_update() -> Result<()> {
let Case { gb_repository, .. } = Suite::default().new_case();
let branch = test_branch();
let mut branch = test_branch();
let target = Target {
branch: "refs/remotes/remote name/branch name".parse().unwrap(),
remote_url: "remote url".to_string(),
@ -272,7 +272,7 @@ mod tests {
};
let branch_writer = branch::Writer::new(&gb_repository);
branch_writer.write(&branch)?;
branch_writer.write(&mut branch)?;
let target_writer = TargetWriter::new(&gb_repository);
target_writer.write(&branch.id, &target)?;

View File

@ -18,7 +18,7 @@ use crate::{
};
use super::*;
use branch::{Branch, BranchCreateRequest, Ownership};
use branch::{BranchCreateRequest, Ownership};
pub fn set_test_target(
gb_repo: &gb_repository::Repository,
@ -731,20 +731,16 @@ fn test_move_hunks_multiple_sources() -> Result<()> {
let current_session_reader = sessions::Reader::open(&gb_repository, &current_session)?;
let branch_reader = branch::Reader::new(&current_session_reader);
let branch_writer = branch::Writer::new(&gb_repository);
let branch2 = branch_reader.read(&branch2_id)?;
branch_writer.write(&branch::Branch {
ownership: Ownership {
files: vec!["test.txt:1-5".parse()?],
},
..branch2
})?;
let branch1 = branch_reader.read(&branch1_id)?;
branch_writer.write(&branch::Branch {
ownership: Ownership {
files: vec!["test.txt:11-15".parse()?],
},
..branch1
})?;
let mut branch2 = branch_reader.read(&branch2_id)?;
branch2.ownership = Ownership {
files: vec!["test.txt:1-5".parse()?],
};
branch_writer.write(&mut branch2)?;
let mut branch1 = branch_reader.read(&branch1_id)?;
branch1.ownership = Ownership {
files: vec!["test.txt:11-15".parse()?],
};
branch_writer.write(&mut branch1)?;
let statuses =
get_status_by_branch(&gb_repository, &project_repository).expect("failed to get status");
@ -1030,7 +1026,7 @@ fn test_merge_vbranch_upstream_clean() -> Result<()> {
branch.upstream = Some(remote_branch.clone());
branch.head = last_push;
branch_writer
.write(&branch)
.write(&mut branch)
.context("failed to write target branch after push")?;
// create the branch
@ -1159,7 +1155,7 @@ fn test_merge_vbranch_upstream_conflict() -> Result<()> {
branch.upstream = Some(remote_branch.clone());
branch.head = last_push;
branch_writer
.write(&branch)
.write(&mut branch)
.context("failed to write target branch after push")?;
// create the branch
@ -1667,13 +1663,11 @@ fn test_detect_mergeable_branch() -> Result<()> {
"line1\nline2\nline3\nline4\nbranch4\n",
)?;
let branch4 = branch_reader.read(&branch4_id)?;
branch_writer.write(&Branch {
ownership: Ownership {
files: vec!["test2.txt:1-6".parse()?],
},
..branch4
})?;
let mut branch4 = branch_reader.read(&branch4_id)?;
branch4.ownership = Ownership {
files: vec!["test2.txt:1-6".parse()?],
};
branch_writer.write(&mut branch4)?;
let branches = list_virtual_branches(&gb_repository, &project_repository)?;
assert_eq!(branches.len(), 4);

View File

@ -49,6 +49,7 @@ pub struct VirtualBranch {
pub upstream: Option<RemoteBranch>, // the upstream branch where this branch pushes to, if any
pub base_current: bool, // is this vbranch based on the current base branch? if false, this needs to be manually merged with conflicts
pub ownership: Ownership,
pub updated_timestamp_ms: u128,
}
// this is the struct that maps to the view `Commit` type in Typescript
@ -231,20 +232,18 @@ pub fn apply_branch(
if merge_index.has_conflicts() {
// currently we can only deal with the merge problem branch
for branch in super::get_status_by_branch(gb_repository, project_repository)?
for mut branch in super::get_status_by_branch(gb_repository, project_repository)?
.into_iter()
.map(|(branch, _)| branch)
.filter(|branch| branch.applied)
{
writer.write(&branch::Branch {
applied: false,
..branch
})?;
branch.applied = false;
writer.write(&mut branch)?;
}
// apply the branch
branch.applied = true;
writer.write(&branch)?;
writer.write(&mut branch)?;
// checkout the conflicts
repo.checkout_index(&mut merge_index)
@ -309,7 +308,7 @@ pub fn apply_branch(
// ok, update the virtual branch
branch.head = new_branch_head;
branch.tree = merged_branch_tree_oid;
writer.write(&branch)?;
writer.write(&mut branch)?;
} else {
// branch was not pushed to upstream yet. attempt a rebase,
let (_, committer) = project_repository.git_signatures(user)?;
@ -401,7 +400,7 @@ pub fn apply_branch(
// apply the branch
branch.applied = true;
writer.write(&branch)?;
writer.write(&mut branch)?;
// checkout the merge index
repo.checkout_index(&mut merge_index)
@ -468,7 +467,7 @@ pub fn unapply_ownership(
if taken_file_ownerships.is_empty() {
continue;
}
branch_writer.write(&branch)?;
branch_writer.write(&mut branch)?;
branch_files = branch_files
.iter_mut()
.filter_map(|(filepath, hunks)| {
@ -611,7 +610,7 @@ pub fn unapply_branch(
target_branch.tree = write_tree(project_repository, &default_target, files)?;
target_branch.applied = false;
branch_writer.write(&target_branch)?;
branch_writer.write(&mut target_branch)?;
}
let repo = &project_repository.git_repository;
@ -831,6 +830,7 @@ pub fn list_virtual_branches(
conflicted: conflicts::is_resolving(project_repository),
base_current,
ownership: branch.ownership.clone(),
updated_timestamp_ms: branch.updated_timestamp_ms,
};
branches.push(branch);
}
@ -1049,7 +1049,7 @@ pub fn create_virtual_branch(
if branch.order != new_order {
branch.order = new_order;
branch_writer
.write(&branch)
.write(&mut branch)
.context("failed to write branch")?;
}
}
@ -1092,7 +1092,7 @@ pub fn create_virtual_branch(
}
branch_writer
.write(&branch)
.write(&mut branch)
.context("failed to write branch")?;
project_repository.add_branch_reference(&branch)?;
@ -1255,7 +1255,7 @@ pub fn merge_virtual_branch_upstream(
let branch_writer = branch::Writer::new(gb_repository);
branch.head = new_branch_head;
branch.tree = merge_tree_oid;
branch_writer.write(&branch)?;
branch_writer.write(&mut branch)?;
}
super::integration::update_gitbutler_integration(gb_repository, project_repository)?;
@ -1339,7 +1339,7 @@ pub fn update_branch(
};
branch_writer
.write(&branch)
.write(&mut branch)
.context("failed to write target branch")?;
Ok(branch)
@ -1796,7 +1796,7 @@ pub fn reset_branch(
})?;
let branch_reader = branch::Reader::new(&current_session_reader);
let branch = match branch_reader.read(branch_id) {
let mut branch = match branch_reader.read(branch_id) {
Ok(branch) => Ok(branch),
Err(reader::Error::NotFound) => Err(errors::ResetBranchError::BranchNotFound(
errors::BranchNotFoundError {
@ -1823,11 +1823,9 @@ pub fn reset_branch(
}
let branch_writer = branch::Writer::new(gb_repository);
branch.head = target_commit_oid;
branch_writer
.write(&branch::Branch {
head: target_commit_oid,
..branch
})
.write(&mut branch)
.context("failed to write branch")?;
super::integration::update_gitbutler_integration(gb_repository, project_repository)
@ -2029,11 +2027,11 @@ pub fn commit(
})?;
// get the files to commit
let statuses = get_status_by_branch(gb_repository, project_repository)
let mut statuses = get_status_by_branch(gb_repository, project_repository)
.context("failed to get status by branch")?;
let (branch, files) = statuses
.iter()
let (ref mut branch, files) = statuses
.iter_mut()
.find(|(branch, _)| branch.id == *branch_id)
.ok_or_else(|| {
errors::CommitError::BranchNotFound(errors::BranchNotFoundError {
@ -2115,13 +2113,9 @@ pub fn commit(
// update the virtual branch head
let writer = branch::Writer::new(gb_repository);
writer
.write(&Branch {
tree: tree_oid,
head: commit_oid,
..branch.clone()
})
.context("failed to write branch")?;
branch.tree = tree_oid;
branch.head = commit_oid;
writer.write(branch).context("failed to write branch")?;
super::integration::update_gitbutler_integration(gb_repository, project_repository)
.context("failed to update gitbutler integration")?;
@ -2147,7 +2141,7 @@ pub fn push(
let branch_reader = branch::Reader::new(&current_session_reader);
let branch_writer = branch::Writer::new(gb_repository);
let vbranch = branch_reader.read(branch_id).map_err(|error| match error {
let mut vbranch = branch_reader.read(branch_id).map_err(|error| match error {
reader::Error::NotFound => errors::PushError::BranchNotFound(errors::BranchNotFoundError {
project_id: project_repository.project().id,
branch_id: *branch_id,
@ -2193,12 +2187,10 @@ pub fn push(
project_repository.push(&vbranch.head, &remote_branch, with_force, credentials)?;
vbranch.upstream = Some(remote_branch.clone());
vbranch.upstream_head = Some(vbranch.head);
branch_writer
.write(&branch::Branch {
upstream: Some(remote_branch.clone()),
upstream_head: Some(vbranch.head),
..vbranch
})
.write(&mut vbranch)
.context("failed to write target branch after push")?;
project_repository.fetch(remote_branch.remote(), credentials)?;
@ -2216,11 +2208,9 @@ pub fn mark_all_unapplied(gb_repository: &gb_repository::Repository) -> Result<(
.context("failed to read branches")?
.into_iter()
.filter(|branch| branch.applied)
.map(|branch| {
branch_writer.write(&super::Branch {
applied: false,
..branch
})
.map(|mut branch| {
branch.applied = false;
branch_writer.write(&mut branch)
})
.collect::<Result<Vec<_>, _>>()
.context("failed to write branches")?;
@ -2487,15 +2477,15 @@ pub fn amend(
})
})?;
let applied_statuses = get_applied_status(
let mut applied_statuses = get_applied_status(
gb_repository,
project_repository,
&default_target,
applied_branches,
)?;
let (target_branch, target_status) = applied_statuses
.iter()
let (ref mut target_branch, target_status) = applied_statuses
.iter_mut()
.find(|(b, _)| b.id == *branch_id)
.ok_or_else(|| {
errors::AmendError::BranchNotFound(errors::BranchNotFoundError {
@ -2592,10 +2582,8 @@ pub fn amend(
.context("failed to create commit")?;
let branch_writer = branch::Writer::new(gb_repository);
branch_writer.write(&branch::Branch {
head: commit_oid,
..target_branch.clone()
})?;
target_branch.head = commit_oid;
branch_writer.write(target_branch)?;
super::integration::update_gitbutler_integration(gb_repository, project_repository)?;
@ -2622,7 +2610,7 @@ pub fn cherry_pick(
let current_session_reader = sessions::Reader::open(gb_repository, &current_session)
.context("failed to open current session")?;
let branch_reader = branch::Reader::new(&current_session_reader);
let branch = branch_reader
let mut branch = branch_reader
.read(branch_id)
.context("failed to read branch")?;
@ -2776,11 +2764,9 @@ pub fn cherry_pick(
// update branch status
let writer = branch::Writer::new(gb_repository);
branch.head = commit_oid;
writer
.write(&Branch {
head: commit_oid,
..branch.clone()
})
.write(&mut branch)
.context("failed to write branch")?;
Some(commit_oid)
@ -2822,7 +2808,7 @@ pub fn squash(
})
})?;
let branch = branch_reader.read(branch_id).map_err(|error| match error {
let mut branch = branch_reader.read(branch_id).map_err(|error| match error {
reader::Error::NotFound => {
errors::SquashError::BranchNotFound(errors::BranchNotFoundError {
project_id: project_repository.project().id,
@ -2970,11 +2956,9 @@ pub fn squash(
// save new branch head
let writer = branch::Writer::new(gb_repository);
branch.head = new_head_id;
writer
.write(&Branch {
head: new_head_id,
..branch.clone()
})
.write(&mut branch)
.context("failed to write branch")?;
super::integration::update_gitbutler_integration(gb_repository, project_repository)?;
@ -3018,7 +3002,7 @@ pub fn update_commit_message(
)
})?;
let branch = branch_reader.read(branch_id).map_err(|error| match error {
let mut branch = branch_reader.read(branch_id).map_err(|error| match error {
reader::Error::NotFound => {
errors::UpdateCommitMessageError::BranchNotFound(errors::BranchNotFoundError {
project_id: project_repository.project().id,
@ -3148,11 +3132,9 @@ pub fn update_commit_message(
// save new branch head
let writer = branch::Writer::new(gb_repository);
branch.head = new_head_id;
writer
.write(&Branch {
head: new_head_id,
..branch.clone()
})
.write(&mut branch)
.context("failed to write branch")?;
super::integration::update_gitbutler_integration(gb_repository, project_repository)?;

View File

@ -815,11 +815,11 @@ mod test {
let target_writer = virtual_branches::target::Writer::new(&gb_repository);
let default_target = test_target();
target_writer.write_default(&default_target)?;
let vbranch0 = test_branch();
branch_writer.write(&vbranch0)?;
let vbranch1 = test_branch();
let mut vbranch0 = test_branch();
branch_writer.write(&mut vbranch0)?;
let mut vbranch1 = test_branch();
let vbranch1_target = test_target();
branch_writer.write(&vbranch1)?;
branch_writer.write(&mut vbranch1)?;
target_writer.write(&vbranch1.id, &vbranch1_target)?;
std::fs::write(project.path.join("test.txt"), "hello world!").unwrap();
@ -871,11 +871,11 @@ mod test {
let target_writer = virtual_branches::target::Writer::new(&gb_repository);
let default_target = test_target();
target_writer.write_default(&default_target)?;
let vbranch0 = test_branch();
branch_writer.write(&vbranch0)?;
let vbranch1 = test_branch();
let mut vbranch0 = test_branch();
branch_writer.write(&mut vbranch0)?;
let mut vbranch1 = test_branch();
let vbranch1_target = test_target();
branch_writer.write(&vbranch1)?;
branch_writer.write(&mut vbranch1)?;
target_writer.write(&vbranch1.id, &vbranch1_target)?;
std::fs::write(project.path.join("test.txt"), "hello world!").unwrap();