gitbutler/crates/gitbutler-branch/tests/virtual_branches/create_commit.rs
2024-07-07 15:51:07 +02:00

299 lines
9.0 KiB
Rust

use gitbutler_branch::VirtualBranch;
use gitbutler_core::{id::Id, virtual_branches::Branch};
use super::*;
#[tokio::test]
async fn should_lock_updated_hunks() {
let Test {
project,
controller,
repository,
..
} = &Test::default();
controller
.set_base_branch(project, &"refs/remotes/origin/master".parse().unwrap())
.await
.unwrap();
let branch_id = controller
.create_virtual_branch(project, &branch::BranchCreateRequest::default())
.await
.unwrap();
{
// by default, hunks are not locked
repository.write_file("file.txt", &["content".to_string()]);
let branch = get_virtual_branch(controller, project, branch_id).await;
assert_eq!(branch.files.len(), 1);
assert_eq!(branch.files[0].path.display().to_string(), "file.txt");
assert_eq!(branch.files[0].hunks.len(), 1);
assert!(!branch.files[0].hunks[0].locked);
}
controller
.create_commit(project, branch_id, "test", None, false)
.await
.unwrap();
{
// change in the committed hunks leads to hunk locking
repository.write_file("file.txt", &["updated content".to_string()]);
let branch = controller
.list_virtual_branches(project)
.await
.unwrap()
.0
.into_iter()
.find(|b| b.id == branch_id)
.unwrap();
assert_eq!(branch.files.len(), 1);
assert_eq!(branch.files[0].path.display().to_string(), "file.txt");
assert_eq!(branch.files[0].hunks.len(), 1);
assert!(branch.files[0].hunks[0].locked);
}
}
#[tokio::test]
async fn should_not_lock_disjointed_hunks() {
let Test {
project,
controller,
repository,
..
} = &Test::default();
let mut lines: Vec<_> = (0_i32..24_i32).map(|i| format!("line {}", i)).collect();
repository.write_file("file.txt", &lines);
repository.commit_all("my commit");
repository.push();
controller
.set_base_branch(project, &"refs/remotes/origin/master".parse().unwrap())
.await
.unwrap();
let branch_id = controller
.create_virtual_branch(project, &branch::BranchCreateRequest::default())
.await
.unwrap();
{
// new hunk in the middle of the file
lines[12] = "commited stuff".to_string();
repository.write_file("file.txt", &lines);
let branch = get_virtual_branch(controller, project, branch_id).await;
assert_eq!(branch.files.len(), 1);
assert_eq!(branch.files[0].path.display().to_string(), "file.txt");
assert_eq!(branch.files[0].hunks.len(), 1);
assert!(!branch.files[0].hunks[0].locked);
}
controller
.create_commit(project, branch_id, "test commit", None, false)
.await
.unwrap();
controller
.push_virtual_branch(project, branch_id, false, None)
.await
.unwrap();
{
// hunk before the commited part is not locked
let mut changed_lines = lines.clone();
changed_lines[8] = "updated line".to_string();
repository.write_file("file.txt", &changed_lines);
let branch = get_virtual_branch(controller, project, branch_id).await;
assert_eq!(branch.files.len(), 1);
assert_eq!(branch.files[0].path.display().to_string(), "file.txt");
assert_eq!(branch.files[0].hunks.len(), 1);
assert!(!branch.files[0].hunks[0].locked);
// cleanup
repository.write_file("file.txt", &lines);
}
{
// hunk after the commited part is not locked
let mut changed_lines = lines.clone();
changed_lines[16] = "updated line".to_string();
repository.write_file("file.txt", &changed_lines);
let branch = get_virtual_branch(controller, project, branch_id).await;
assert_eq!(branch.files.len(), 1);
assert_eq!(branch.files[0].path.display().to_string(), "file.txt");
assert_eq!(branch.files[0].hunks.len(), 1);
assert!(!branch.files[0].hunks[0].locked);
// cleanup
repository.write_file("file.txt", &lines);
}
{
// hunk before the commited part but with overlapping context
let mut changed_lines = lines.clone();
changed_lines[10] = "updated line".to_string();
repository.write_file("file.txt", &changed_lines);
let branch = get_virtual_branch(controller, project, branch_id).await;
assert_eq!(branch.files.len(), 1);
assert_eq!(branch.files[0].path.display().to_string(), "file.txt");
assert_eq!(branch.files[0].hunks.len(), 1);
// TODO: We lock this hunk, but can we afford not lock it?
assert!(branch.files[0].hunks[0].locked);
// cleanup
repository.write_file("file.txt", &lines);
}
{
// hunk after the commited part but with overlapping context
let mut changed_lines = lines.clone();
changed_lines[14] = "updated line".to_string();
repository.write_file("file.txt", &changed_lines);
let branch = get_virtual_branch(controller, project, branch_id).await;
assert_eq!(branch.files.len(), 1);
assert_eq!(branch.files[0].path.display().to_string(), "file.txt");
assert_eq!(branch.files[0].hunks.len(), 1);
// TODO: We lock this hunk, but can we afford not lock it?
assert!(branch.files[0].hunks[0].locked);
// cleanup
repository.write_file("file.txt", &lines);
}
}
#[tokio::test]
async fn should_reset_into_same_branch() {
let Test {
project,
controller,
repository,
..
} = &Test::default();
let mut lines = repository.gen_file("file.txt", 7);
commit_and_push_initial(repository);
let base_branch = controller
.set_base_branch(project, &"refs/remotes/origin/master".parse().unwrap())
.await
.unwrap();
controller
.create_virtual_branch(project, &branch::BranchCreateRequest::default())
.await
.unwrap();
let branch_2_id = controller
.create_virtual_branch(
project,
&branch::BranchCreateRequest {
selected_for_changes: Some(true),
..Default::default()
},
)
.await
.unwrap();
lines[0] = "change 1".to_string();
repository.write_file("file.txt", &lines);
controller
.create_commit(project, branch_2_id, "commit to branch 2", None, false)
.await
.unwrap();
let files = get_virtual_branch(controller, project, branch_2_id)
.await
.files;
assert_eq!(files.len(), 0);
// Set target to branch 1 and verify the file resets into branch 2.
controller
.update_virtual_branch(
project,
branch::BranchUpdateRequest {
id: branch_2_id,
selected_for_changes: Some(true),
..Default::default()
},
)
.await
.unwrap();
controller
.reset_virtual_branch(project, branch_2_id, base_branch.base_sha)
.await
.unwrap();
let files = get_virtual_branch(controller, project, branch_2_id)
.await
.files;
assert_eq!(files.len(), 1);
}
#[tokio::test]
async fn should_double_lock() {
let Test {
project,
controller,
repository,
..
} = &Test::default();
let mut lines = repository.gen_file("file.txt", 7);
repository.write_file("file.txt", &lines);
commit_and_push_initial(repository);
controller
.set_base_branch(project, &"refs/remotes/origin/master".parse().unwrap())
.await
.unwrap();
let branch_id = controller
.create_virtual_branch(project, &branch::BranchCreateRequest::default())
.await
.unwrap();
lines[0] = "change 1".to_string();
repository.write_file("file.txt", &lines);
let commit_1 = controller
.create_commit(project, branch_id, "commit 1", None, false)
.await
.unwrap();
lines[6] = "change 2".to_string();
repository.write_file("file.txt", &lines);
let commit_2 = controller
.create_commit(project, branch_id, "commit 2", None, false)
.await
.unwrap();
lines[3] = "change3".to_string();
repository.write_file("file.txt", &lines);
let branch = get_virtual_branch(controller, project, branch_id).await;
let locks = &branch.files[0].hunks[0].locked_to.clone().unwrap();
assert_eq!(locks.len(), 2);
assert_eq!(locks[0].commit_id, commit_1);
assert_eq!(locks[1].commit_id, commit_2);
}
fn commit_and_push_initial(repository: &TestProject) {
repository.commit_all("initial commit");
repository.push();
}
async fn get_virtual_branch(
controller: &Controller,
project: &Project,
branch_id: Id<Branch>,
) -> VirtualBranch {
controller
.list_virtual_branches(project)
.await
.unwrap()
.0
.into_iter()
.find(|b| b.id == branch_id)
.unwrap()
}