gitbutler/crates/gitbutler-branch-actions/tests/virtual_branches/locking.rs
Mattias Granlund d9156fc00b Integrate new hunk dependency algorithm
- behind a project level feature flag
2024-10-23 22:42:46 +02:00

132 lines
4.8 KiB
Rust

use super::*;
use gitbutler_branch::BranchCreateRequest;
use gitbutler_branch_actions::{
create_commit, create_virtual_branch, list_virtual_branches, set_base_branch,
};
// This test ensures hunk lock detection works when a lines are shifted.
//
// The idea is you introduce change A, then you shift it down in a a different
// (default) branch with commit B, so that new line numbers no longer intersect
// with those applied to the isolated branch.
#[tokio::test]
async fn hunk_locking_confused_by_line_number_shift() -> anyhow::Result<()> {
let Test {
repository,
project,
..
} = &Test::default();
let mut lines = repository.gen_file("file.txt", 9);
repository.commit_all("initial commit");
repository.push();
set_base_branch(project, &"refs/remotes/origin/master".parse().unwrap()).unwrap();
// Introduce a change that should lock the last change to the first branch.
lines[8] = "modification 1 to line 8".to_string();
repository.write_file("file.txt", &lines);
// We're forced to call this before making a second commit.
let (branches, _) = list_virtual_branches(project).unwrap();
create_commit(project, branches[0].id, "first commit", None, false)?;
let (branches, _) = list_virtual_branches(project).unwrap();
assert_eq!(branches[0].files.len(), 0);
assert_eq!(branches[0].commits.len(), 1);
// Commit some changes to the second branch that will push the first
// changes down when diffing workspace head against the default target.
create_virtual_branch(
project,
&BranchCreateRequest {
selected_for_changes: Some(true),
..Default::default()
},
)
.unwrap();
let new_lines: Vec<_> = (0_i32..5_i32)
.map(|i| format!("inserted line {}", i))
.collect();
lines.splice(0..0, new_lines);
repository.write_file("file.txt", &lines);
// We're forced to call this before making a second commit.
let (branches, _) = list_virtual_branches(project).unwrap();
create_commit(project, branches[1].id, "second commit", None, false)?;
// At this point we expect no uncommitted files, and one commit per branch.
let (branches, _) = list_virtual_branches(project).unwrap();
assert_eq!(branches[0].commits.len(), 1);
assert_eq!(branches[0].files.len(), 0);
assert_eq!(branches[1].commits.len(), 1);
assert_eq!(branches[1].files.len(), 0);
// Now we change line we already changed in the first commit.
lines[13] = "modification 2 to original line 8".to_string();
repository.write_file("file.txt", &lines);
// And ensure that the new change is assigned to the first branch, despite the second
// branch being default for new changes.
let (branches, _) = list_virtual_branches(project).unwrap();
assert_eq!(branches[0].files.len(), 1);
// For good measure, let's ensure the hunk lock points to the right branch.
let branch = &branches[0];
let file = &branch.files[0];
let hunk_locks = file.hunks[0].locked_to.clone().unwrap();
assert_eq!(hunk_locks[0].branch_id, branch.id);
Ok(())
}
// This test ensures hunk lock detection works when a lines are shifted.
//
// The idea is you introduce change A, then you shift it down in a a different
// (default) branch with commit B, so that new line numbers no longer intersect
// with those applied to the isolated branch.
#[tokio::test]
async fn hunk_locking_with_deleted_lines_only() -> anyhow::Result<()> {
let Test {
repository,
project,
..
} = &Test::default();
repository.gen_file("file.txt", 3);
repository.commit_all("initial commit");
repository.push();
set_base_branch(project, &"refs/remotes/origin/master".parse().unwrap()).unwrap();
// Introduce a change that should lock the last change to the first branch.
let mut lines = repository.gen_file("file.txt", 2);
lines[1] = "line 2".to_string();
repository.write_file("file.txt", &lines);
// We have to do this before creating a commit.
let (branches, _) = list_virtual_branches(project).unwrap();
create_commit(project, branches[0].id, "first commit", None, false)?;
let (branches, _) = list_virtual_branches(project).unwrap();
assert_eq!(branches[0].commits.len(), 1);
assert_eq!(branches[0].files.len(), 0);
// Commit some changes to the second branch that will push the first changes
// down when diffing workspace head against the default target.
create_virtual_branch(
project,
&BranchCreateRequest {
selected_for_changes: Some(true),
..Default::default()
},
)
.unwrap();
lines[1] = "modified line 2".to_string();
repository.write_file("file.txt", &lines);
let (branches, _) = list_virtual_branches(project)?;
assert_eq!(branches[0].files.len(), 1);
assert_eq!(branches[1].files.len(), 0);
Ok(())
}