From 0cdf1871154df0602435f23ffa7b63a66d5497f4 Mon Sep 17 00:00:00 2001 From: Nikita Galaiko Date: Wed, 13 Dec 2023 15:25:01 +0100 Subject: [PATCH] ensure branch updated time is always up to date --- .../tauri/src/gb_repository/repository.rs | 4 +- packages/tauri/src/virtual_branches/base.rs | 342 +++++++++--------- .../src/virtual_branches/branch/reader.rs | 4 +- .../src/virtual_branches/branch/writer.rs | 22 +- .../tauri/src/virtual_branches/integration.rs | 10 +- .../tauri/src/virtual_branches/iterator.rs | 12 +- .../src/virtual_branches/target/reader.rs | 4 +- .../src/virtual_branches/target/writer.rs | 8 +- packages/tauri/src/virtual_branches/tests.rs | 42 +-- .../tauri/src/virtual_branches/virtual.rs | 106 +++--- .../handlers/calculate_deltas_handler.rs | 16 +- 11 files changed, 264 insertions(+), 306 deletions(-) diff --git a/packages/tauri/src/gb_repository/repository.rs b/packages/tauri/src/gb_repository/repository.rs index 41201a945..3361e8375 100644 --- a/packages/tauri/src/gb_repository/repository.rs +++ b/packages/tauri/src/gb_repository/repository.rs @@ -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))?; } diff --git a/packages/tauri/src/virtual_branches/base.rs b/packages/tauri/src/virtual_branches/base.rs index 78982cdd7..28e2a1e47 100644 --- a/packages/tauri/src/virtual_branches/base.rs +++ b/packages/tauri/src/virtual_branches/base.rs @@ -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> { - let branch_tree = repo.find_tree(branch.tree)?; + .map( + |mut branch: branch::Branch| -> Result> { + 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::>>()? .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)?; diff --git a/packages/tauri/src/virtual_branches/branch/reader.rs b/packages/tauri/src/virtual_branches/branch/reader.rs index aa6613aee..39c78d195 100644 --- a/packages/tauri/src/virtual_branches/branch/reader.rs +++ b/packages/tauri/src/virtual_branches/branch/reader.rs @@ -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)?; diff --git a/packages/tauri/src/virtual_branches/branch/writer.rs b/packages/tauri/src/virtual_branches/branch/writer.rs index f6bea1cce..6fa5ae25f 100644 --- a/packages/tauri/src/virtual_branches/branch/writer.rs +++ b/packages/tauri/src/virtual_branches/branch/writer.rs @@ -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() diff --git a/packages/tauri/src/virtual_branches/integration.rs b/packages/tauri/src/virtual_branches/integration.rs index a0f78f095..4022cfab6 100644 --- a/packages/tauri/src/virtual_branches/integration.rs +++ b/packages/tauri/src/virtual_branches/integration.rs @@ -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(); diff --git a/packages/tauri/src/virtual_branches/iterator.rs b/packages/tauri/src/virtual_branches/iterator.rs index 6b6d0ef2b..b2adabcb5 100644 --- a/packages/tauri/src/virtual_branches/iterator.rs +++ b/packages/tauri/src/virtual_branches/iterator.rs @@ -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)?; diff --git a/packages/tauri/src/virtual_branches/target/reader.rs b/packages/tauri/src/virtual_branches/target/reader.rs index 18420bfca..eee63d6fe 100644 --- a/packages/tauri/src/virtual_branches/target/reader.rs +++ b/packages/tauri/src/virtual_branches/target/reader.rs @@ -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)?; diff --git a/packages/tauri/src/virtual_branches/target/writer.rs b/packages/tauri/src/virtual_branches/target/writer.rs index 04d4adfee..9cf607d81 100644 --- a/packages/tauri/src/virtual_branches/target/writer.rs +++ b/packages/tauri/src/virtual_branches/target/writer.rs @@ -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)?; diff --git a/packages/tauri/src/virtual_branches/tests.rs b/packages/tauri/src/virtual_branches/tests.rs index 650de570c..a7ebf9f38 100644 --- a/packages/tauri/src/virtual_branches/tests.rs +++ b/packages/tauri/src/virtual_branches/tests.rs @@ -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, ¤t_session)?; let branch_reader = branch::Reader::new(¤t_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); diff --git a/packages/tauri/src/virtual_branches/virtual.rs b/packages/tauri/src/virtual_branches/virtual.rs index d8a74ad5e..79a096d36 100644 --- a/packages/tauri/src/virtual_branches/virtual.rs +++ b/packages/tauri/src/virtual_branches/virtual.rs @@ -49,6 +49,7 @@ pub struct VirtualBranch { pub upstream: Option, // 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(¤t_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(¤t_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::, _>>() .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, ¤t_session) .context("failed to open current session")?; let branch_reader = branch::Reader::new(¤t_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)?; diff --git a/packages/tauri/src/watcher/handlers/calculate_deltas_handler.rs b/packages/tauri/src/watcher/handlers/calculate_deltas_handler.rs index 64a0a147c..5706dae6d 100644 --- a/packages/tauri/src/watcher/handlers/calculate_deltas_handler.rs +++ b/packages/tauri/src/watcher/handlers/calculate_deltas_handler.rs @@ -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();