gitbutler/crates/gitbutler-branch-actions/tests/virtual_branches/update_base_branch.rs
Sebastian Thiel 4d495cb3bc
Adjust integration check to also recognize by matching tree.
This is relevant when all commits are equal by tree, but seem changed
due to the added GitButler headers.

For added safety, we also compare by commit message, date and authors,
basically everything that isn't the headers.
2024-08-30 07:15:47 +02:00

1049 lines
36 KiB
Rust

use super::*;
mod applied_branch {
use gitbutler_branch::BranchCreateRequest;
use super::*;
#[test]
fn conflicts_with_uncommitted_work() {
let Test {
repository,
project,
controller,
..
} = &Test::default();
// make sure we have an undiscovered commit in the remote branch
{
fs::write(repository.path().join("file.txt"), "first").unwrap();
let first_commit_oid = repository.commit_all("first");
fs::write(repository.path().join("file.txt"), "second").unwrap();
repository.commit_all("second");
repository.push();
repository.reset_hard(Some(first_commit_oid));
}
controller
.set_base_branch(project, &"refs/remotes/origin/master".parse().unwrap())
.unwrap();
{
// make a branch that conflicts with the remote branch, but doesn't know about it yet
controller
.create_virtual_branch(project, &BranchCreateRequest::default())
.unwrap();
fs::write(repository.path().join("file.txt"), "conflict").unwrap();
}
let unapplied_branch = {
// fetch remote
let unapplied_branches = controller.update_base_branch(project).unwrap();
assert_eq!(unapplied_branches.len(), 1);
// should stash conflicting branch
let (branches, _) = controller.list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 0);
Refname::from_str(unapplied_branches[0].as_str()).unwrap()
};
{
// applying the branch should produce conflict markers
controller
.create_virtual_branch_from_branch(project, &unapplied_branch, None)
.unwrap();
let (branches, _) = controller.list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 1);
assert!(branches[0].conflicted);
assert!(branches[0].base_current);
assert_eq!(branches[0].files.len(), 1);
assert_eq!(
std::fs::read_to_string(repository.path().join("file.txt")).unwrap(),
"<<<<<<< ours\nconflict\n=======\nsecond\n>>>>>>> theirs\n"
);
}
}
#[test]
fn commited_conflict_not_pushed() {
let Test {
repository,
project,
controller,
..
} = &Test::default();
// make sure we have an undiscovered commit in the remote branch
{
fs::write(repository.path().join("file.txt"), "first").unwrap();
let first_commit_oid = repository.commit_all("first");
fs::write(repository.path().join("file.txt"), "second").unwrap();
repository.commit_all("second");
repository.push();
repository.reset_hard(Some(first_commit_oid));
}
controller
.set_base_branch(project, &"refs/remotes/origin/master".parse().unwrap())
.unwrap();
{
// make a branch with a commit that conflicts with upstream, and work that fixes
// that conflict
let branch_id = controller
.create_virtual_branch(project, &BranchCreateRequest::default())
.unwrap();
fs::write(repository.path().join("file.txt"), "conflict").unwrap();
controller
.create_commit(project, branch_id, "conflicting commit", None, false)
.unwrap();
}
let unapplied_branch = {
// when fetching remote
let unapplied_branches = controller.update_base_branch(project).unwrap();
assert_eq!(unapplied_branches.len(), 1);
// should stash the branch.
let (branches, _) = controller.list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 0);
Refname::from_str(unapplied_branches[0].as_str()).unwrap()
};
{
// applying the branch should produce conflict markers
controller
.create_virtual_branch_from_branch(project, &unapplied_branch, None)
.unwrap();
let (branches, _) = controller.list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 1);
assert!(branches[0].conflicted);
assert!(branches[0].base_current);
assert_eq!(branches[0].files.len(), 1);
assert_eq!(branches[0].commits.len(), 1);
assert_eq!(
std::fs::read_to_string(repository.path().join("file.txt")).unwrap(),
"<<<<<<< ours\nconflict\n=======\nsecond\n>>>>>>> theirs\n"
);
}
}
#[test]
fn commited_conflict_pushed() {
let Test {
repository,
project,
controller,
..
} = &Test::default();
// make sure we have an undiscovered commit in the remote branch
{
fs::write(repository.path().join("file.txt"), "first").unwrap();
let first_commit_oid = repository.commit_all("first");
fs::write(repository.path().join("file.txt"), "second").unwrap();
repository.commit_all("second");
repository.push();
repository.reset_hard(Some(first_commit_oid));
}
controller
.set_base_branch(project, &"refs/remotes/origin/master".parse().unwrap())
.unwrap();
{
// make a branch with a commit that conflicts with upstream, and work that fixes
// that conflict
let branch_id = controller
.create_virtual_branch(project, &BranchCreateRequest::default())
.unwrap();
fs::write(repository.path().join("file.txt"), "conflict").unwrap();
controller
.create_commit(project, branch_id, "conflicting commit", None, false)
.unwrap();
controller
.push_virtual_branch(project, branch_id, false, None)
.unwrap();
}
let unapplied_branch = {
// when fetching remote
let unapplied_branches = controller.update_base_branch(project).unwrap();
assert_eq!(unapplied_branches.len(), 1);
// should stash the branch.
let (branches, _) = controller.list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 0);
Refname::from_str(unapplied_branches[0].as_str()).unwrap()
};
{
// applying the branch should produce conflict markers
controller
.create_virtual_branch_from_branch(project, &unapplied_branch, None)
.unwrap();
let (branches, _) = controller.list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 1);
assert!(branches[0].conflicted);
assert!(branches[0].base_current);
assert_eq!(branches[0].files.len(), 1);
assert_eq!(branches[0].commits.len(), 1);
assert_eq!(
std::fs::read_to_string(repository.path().join("file.txt")).unwrap(),
"<<<<<<< ours\nconflict\n=======\nsecond\n>>>>>>> theirs\n"
);
}
}
#[test]
fn commited_conflict_not_pushed_fixed_with_more_work() {
let Test {
repository,
project,
controller,
..
} = &Test::default();
// make sure we have an undiscovered commit in the remote branch
{
fs::write(repository.path().join("file.txt"), "first").unwrap();
let first_commit_oid = repository.commit_all("first");
fs::write(repository.path().join("file.txt"), "second").unwrap();
repository.commit_all("second");
repository.push();
repository.reset_hard(Some(first_commit_oid));
}
controller
.set_base_branch(project, &"refs/remotes/origin/master".parse().unwrap())
.unwrap();
{
// make a branch with a commit that conflicts with upstream, and work that fixes
// that conflict
let branch_id = controller
.create_virtual_branch(project, &BranchCreateRequest::default())
.unwrap();
fs::write(repository.path().join("file.txt"), "conflict").unwrap();
controller
.create_commit(project, branch_id, "conflicting commit", None, false)
.unwrap();
fs::write(repository.path().join("file.txt"), "fix conflict").unwrap();
}
let unapplied_branch = {
// when fetching remote
let unapplied_branches = controller.update_base_branch(project).unwrap();
assert_eq!(unapplied_branches.len(), 1);
// should rebase upstream, and leave uncommited file as is
let (branches, _) = controller.list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 0);
Refname::from_str(unapplied_branches[0].as_str()).unwrap()
};
{
// applying the branch should produce conflict markers
controller
.create_virtual_branch_from_branch(project, &unapplied_branch, None)
.unwrap();
let (branches, _) = controller.list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 1);
assert!(branches[0].conflicted);
assert!(branches[0].base_current);
assert_eq!(branches[0].files.len(), 1);
assert_eq!(branches[0].commits.len(), 2);
assert_eq!(
std::fs::read_to_string(repository.path().join("file.txt")).unwrap(),
"<<<<<<< ours\nfix conflict\n=======\nsecond\n>>>>>>> theirs\n"
);
}
}
#[test]
fn commited_conflict_pushed_fixed_with_more_work() {
let Test {
repository,
project,
controller,
..
} = &Test::default();
// make sure we have an undiscovered commit in the remote branch
{
fs::write(repository.path().join("file.txt"), "first").unwrap();
let first_commit_oid = repository.commit_all("first");
fs::write(repository.path().join("file.txt"), "second").unwrap();
repository.commit_all("second");
repository.push();
repository.reset_hard(Some(first_commit_oid));
}
controller
.set_base_branch(project, &"refs/remotes/origin/master".parse().unwrap())
.unwrap();
{
// make a branch with a commit that conflicts with upstream, and work that fixes
// that conflict
let branch_id = controller
.create_virtual_branch(project, &BranchCreateRequest::default())
.unwrap();
fs::write(repository.path().join("file.txt"), "conflict").unwrap();
controller
.create_commit(project, branch_id, "conflicting commit", None, false)
.unwrap();
fs::write(repository.path().join("file.txt"), "fix conflict").unwrap();
}
let unapplied_branch = {
// when fetching remote
let unapplied_branches = controller.update_base_branch(project).unwrap();
assert_eq!(unapplied_branches.len(), 1);
// should merge upstream, and leave uncommited file as is.
let (branches, _) = controller.list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 0);
Refname::from_str(unapplied_branches[0].as_str()).unwrap()
};
{
// applying the branch should produce conflict markers
controller
.create_virtual_branch_from_branch(project, &unapplied_branch, None)
.unwrap();
let (branches, _) = controller.list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 1);
assert!(branches[0].conflicted);
assert!(branches[0].base_current);
assert_eq!(branches[0].files.len(), 1);
assert_eq!(branches[0].commits.len(), 2);
assert_eq!(
std::fs::read_to_string(repository.path().join("file.txt")).unwrap(),
"<<<<<<< ours\nfix conflict\n=======\nsecond\n>>>>>>> theirs\n"
);
}
}
mod no_conflicts_pushed {
use gitbutler_branch::BranchUpdateRequest;
use super::*;
#[test]
fn force_push_ok() {
let Test {
repository,
project,
project_id,
controller,
projects,
..
} = &Test::default();
// make sure we have an undiscovered commit in the remote branch
{
fs::write(repository.path().join("file.txt"), "first").unwrap();
let first_commit_oid = repository.commit_all("first");
fs::write(repository.path().join("file.txt"), "second").unwrap();
repository.commit_all("second");
repository.push();
repository.reset_hard(Some(first_commit_oid));
}
projects
.update(&projects::UpdateRequest {
id: *project_id,
..Default::default()
})
.unwrap();
controller
.set_base_branch(project, &"refs/remotes/origin/master".parse().unwrap())
.unwrap();
let branch_id = {
let branch_id = controller
.create_virtual_branch(project, &BranchCreateRequest::default())
.unwrap();
fs::write(repository.path().join("file2.txt"), "no conflict").unwrap();
controller
.create_commit(project, branch_id, "no conflicts", None, false)
.unwrap();
controller
.push_virtual_branch(project, branch_id, false, None)
.unwrap();
fs::write(repository.path().join("file2.txt"), "still no conflict").unwrap();
branch_id
};
{
// fetch remote
controller.update_base_branch(project).unwrap();
// rebases branch, since the branch is pushed and force pushing is
// allowed
let (branches, _) = controller.list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 1);
assert_eq!(branches[0].id, branch_id);
assert!(branches[0].active);
assert!(branches[0].requires_force);
assert!(branches[0].base_current);
assert_eq!(branches[0].files.len(), 1);
assert_eq!(branches[0].commits.len(), 1);
assert!(!branches[0].commits[0].is_remote);
assert!(
branches[0].commits[0].copied_from_remote_id.is_some(),
"it's copied, which displays things differently in the \
UI which knows what remote commit it relates to"
);
assert!(!branches[0].commits[0].is_integrated);
}
}
#[test]
fn force_push_not_ok() {
let Test {
repository,
project,
controller,
..
} = &Test::default();
// make sure we have an undiscovered commit in the remote branch
{
fs::write(repository.path().join("file.txt"), "first").unwrap();
let first_commit_oid = repository.commit_all("first");
fs::write(repository.path().join("file.txt"), "second").unwrap();
repository.commit_all("second");
repository.push();
repository.reset_hard(Some(first_commit_oid));
}
controller
.set_base_branch(project, &"refs/remotes/origin/master".parse().unwrap())
.unwrap();
let branch_id = {
let branch_id = controller
.create_virtual_branch(project, &BranchCreateRequest::default())
.unwrap();
fs::write(repository.path().join("file2.txt"), "no conflict").unwrap();
controller
.create_commit(project, branch_id, "no conflicts", None, false)
.unwrap();
controller
.push_virtual_branch(project, branch_id, false, None)
.unwrap();
fs::write(repository.path().join("file2.txt"), "still no conflict").unwrap();
branch_id
};
controller
.update_virtual_branch(
project,
BranchUpdateRequest {
id: branch_id,
allow_rebasing: Some(false),
..Default::default()
},
)
.unwrap();
{
// fetch remote
controller.update_base_branch(project).unwrap();
// creates a merge commit, since the branch is pushed
let (branches, _) = controller.list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 1);
assert_eq!(branches[0].id, branch_id);
assert!(branches[0].active);
assert!(!branches[0].requires_force);
assert!(branches[0].base_current);
assert_eq!(branches[0].files.len(), 1);
assert_eq!(branches[0].commits.len(), 2);
assert!(!branches[0].commits[0].is_remote);
assert!(!branches[0].commits[0].is_integrated);
assert!(branches[0].commits[1].is_remote);
assert!(!branches[0].commits[1].is_integrated);
}
}
}
#[test]
fn no_conflicts() {
let Test {
repository,
project,
controller,
..
} = &Test::default();
// make sure we have an undiscovered commit in the remote branch
{
fs::write(repository.path().join("file.txt"), "first").unwrap();
let first_commit_oid = repository.commit_all("first");
fs::write(repository.path().join("file.txt"), "second").unwrap();
repository.commit_all("second");
repository.push();
repository.reset_hard(Some(first_commit_oid));
}
controller
.set_base_branch(project, &"refs/remotes/origin/master".parse().unwrap())
.unwrap();
let branch_id = {
let branch_id = controller
.create_virtual_branch(project, &BranchCreateRequest::default())
.unwrap();
fs::write(repository.path().join("file2.txt"), "no conflict").unwrap();
controller
.create_commit(project, branch_id, "no conflicts", None, false)
.unwrap();
fs::write(repository.path().join("file2.txt"), "still no conflict").unwrap();
branch_id
};
{
// fetch remote
controller.update_base_branch(project).unwrap();
// just rebases branch
let (branches, _) = controller.list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 1);
assert_eq!(branches[0].id, branch_id);
assert!(branches[0].active);
assert!(branches[0].base_current);
assert_eq!(branches[0].files.len(), 1);
assert_eq!(branches[0].commits.len(), 1);
assert_eq!(
std::fs::read_to_string(repository.path().join("file.txt")).unwrap(),
"second"
);
assert_eq!(
std::fs::read_to_string(repository.path().join("file2.txt")).unwrap(),
"still no conflict"
);
}
}
#[test]
fn integrated_commit_plus_work() {
let Test {
repository,
project,
controller,
..
} = &Test::default();
{
fs::write(repository.path().join("file.txt"), "first").unwrap();
repository.commit_all("first");
repository.push();
}
controller
.set_base_branch(project, &"refs/remotes/origin/master".parse().unwrap())
.unwrap();
let branch_id = {
// make a branch that conflicts with the remote branch, but doesn't know about it yet
let branch_id = controller
.create_virtual_branch(project, &BranchCreateRequest::default())
.unwrap();
fs::write(repository.path().join("file.txt"), "second").unwrap();
controller
.create_commit(project, branch_id, "second", None, false)
.unwrap();
controller
.push_virtual_branch(project, branch_id, false, None)
.unwrap();
{
// merge branch upstream
let branch = controller
.list_virtual_branches(project)
.unwrap()
.0
.into_iter()
.find(|b| b.id == branch_id)
.unwrap();
repository.merge(&branch.upstream.as_ref().unwrap().name);
repository.fetch();
}
// more local work in the same branch
fs::write(repository.path().join("file2.txt"), "other").unwrap();
branch_id
};
{
// fetch remote
controller.update_base_branch(project).unwrap();
// should remove integrated commit, but leave non integrated work as is
let (branches, _) = controller.list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 1);
assert_eq!(branches[0].id, branch_id);
assert!(branches[0].active);
assert!(branches[0].base_current);
assert_eq!(branches[0].files.len(), 1);
assert_eq!(branches[0].commits.len(), 0);
assert_eq!(
std::fs::read_to_string(repository.path().join("file.txt")).unwrap(),
"second"
);
assert_eq!(
std::fs::read_to_string(repository.path().join("file2.txt")).unwrap(),
"other"
);
}
}
#[test]
fn integrated_with_locked_conflicting_hunks() {
let Test {
repository,
project,
controller,
..
} = &Test::default();
// make sure we have an undiscovered commit in the remote branch
{
fs::write(
repository.path().join("file.txt"),
"1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n",
)
.unwrap();
let first_commit_oid = repository.commit_all("first");
fs::write(
repository.path().join("file.txt"),
"1\n2\n3\n4\n5\n6\n17\n8\n9\n10\n11\n12\n",
)
.unwrap();
repository.commit_all("second");
repository.push();
repository.reset_hard(Some(first_commit_oid));
}
controller
.set_base_branch(project, &"refs/remotes/origin/master".parse().unwrap())
.unwrap();
// branch has no conflict
let branch_id = {
let branch_id = controller
.create_virtual_branch(project, &BranchCreateRequest::default())
.unwrap();
fs::write(
repository.path().join("file.txt"),
"1\n2\n3\n4\n5\n6\n7\n8\n19\n10\n11\n12\n",
)
.unwrap();
controller
.create_commit(project, branch_id, "fourth", None, false)
.unwrap();
branch_id
};
// push the branch
controller
.push_virtual_branch(project, branch_id, false, None)
.unwrap();
// another locked conflicting hunk
fs::write(
repository.path().join("file.txt"),
"1\n2\n3\n4\n5\n6\n77\n8\n19\n10\n11\n12\n",
)
.unwrap();
{
// merge branch remotely
let branch = controller.list_virtual_branches(project).unwrap().0[0].clone();
repository.merge(&branch.upstream.as_ref().unwrap().name);
}
repository.fetch();
let unapplied_refname = {
let unapplied_refnames = controller.update_base_branch(project).unwrap();
assert_eq!(unapplied_refnames.len(), 1);
// removes integrated commit, leaves non commited work as is
let (branches, _) = controller.list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 0);
assert_eq!(
fs::read_to_string(repository.path().join("file.txt")).unwrap(),
"1\n2\n3\n4\n5\n6\n17\n8\n19\n10\n11\n12\n"
);
unapplied_refnames[0].clone()
};
{
controller
.create_virtual_branch_from_branch(
project,
&Refname::from_str(unapplied_refname.as_str()).unwrap(),
None,
)
.unwrap();
let vb_state = VirtualBranchesHandle::new(project.gb_dir());
let ctx = CommandContext::open(project).unwrap();
update_gitbutler_integration(&vb_state, &ctx).unwrap();
let (branches, _) = controller.list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 1);
assert!(branches[0].active);
assert!(branches[0].conflicted);
assert!(branches[0].base_current);
assert_eq!(branches[0].files.len(), 1);
assert_eq!(branches[0].files[0].hunks.len(), 1);
assert_eq!(
branches[0].files[0].hunks[0].diff,
"@@ -4,7 +4,11 @@\n 4\n 5\n 6\n-7\n+<<<<<<< ours\n+77\n+=======\n+17\n+>>>>>>> theirs\n 8\n 19\n 10\n"
);
}
}
#[test]
fn integrated_with_locked_hunks() {
let Test {
repository,
project,
project_id,
controller,
projects,
..
} = &Test::default();
projects
.update(&projects::UpdateRequest {
id: *project_id,
..Default::default()
})
.unwrap();
controller
.set_base_branch(project, &"refs/remotes/origin/master".parse().unwrap())
.unwrap();
let branch_id = {
let branch_id = controller
.create_virtual_branch(project, &BranchCreateRequest::default())
.unwrap();
fs::write(repository.path().join("file.txt"), "first").unwrap();
controller
.create_commit(project, branch_id, "first", None, false)
.unwrap();
branch_id
};
controller
.push_virtual_branch(project, branch_id, false, None)
.unwrap();
// another non-locked hunk
fs::write(repository.path().join("file.txt"), "first\nsecond").unwrap();
{
// push and merge branch remotely
let branch = controller.list_virtual_branches(project).unwrap().0[0].clone();
repository.merge(&branch.upstream.as_ref().unwrap().name);
}
repository.fetch();
{
controller.update_base_branch(project).unwrap();
// removes integrated commit, leaves non commited work as is
let (branches, _) = controller.list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 1);
assert_eq!(branches[0].id, branch_id);
assert!(branches[0].active);
assert!(branches[0].commits.is_empty());
assert!(branches[0].upstream.is_none());
assert_eq!(branches[0].files.len(), 1);
}
}
#[test]
fn integrated_with_non_locked_hunks() {
let Test {
repository,
project,
controller,
..
} = &Test::default();
controller
.set_base_branch(project, &"refs/remotes/origin/master".parse().unwrap())
.unwrap();
let branch_id = {
// make a branch that conflicts with the remote branch, but doesn't know about it yet
let branch_id = controller
.create_virtual_branch(project, &BranchCreateRequest::default())
.unwrap();
fs::write(repository.path().join("file.txt"), "first").unwrap();
controller
.create_commit(project, branch_id, "first", None, false)
.unwrap();
branch_id
};
controller
.push_virtual_branch(project, branch_id, false, None)
.unwrap();
// another non-locked hunk
fs::write(repository.path().join("another_file.txt"), "first").unwrap();
{
// push and merge branch remotely
let branch = controller.list_virtual_branches(project).unwrap().0[0].clone();
repository.merge(&branch.upstream.as_ref().unwrap().name);
}
repository.fetch();
{
controller.update_base_branch(project).unwrap();
// removes integrated commit, leaves non commited work as is
let (branches, _) = controller.list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 1);
assert_eq!(branches[0].id, branch_id);
assert!(branches[0].active);
assert!(branches[0].commits.is_empty());
assert!(branches[0].upstream.is_none());
assert_eq!(branches[0].files.len(), 1);
}
}
#[test]
fn all_integrated() {
let Test {
repository,
project,
controller,
..
} = &Test::default();
// make sure we have an undiscovered commit in the remote branch
{
fs::write(repository.path().join("file.txt"), "first").unwrap();
let first_commit_oid = repository.commit_all("first");
fs::write(repository.path().join("file.txt"), "second").unwrap();
repository.commit_all("second");
repository.push();
repository.reset_hard(Some(first_commit_oid));
}
controller
.set_base_branch(project, &"refs/remotes/origin/master".parse().unwrap())
.unwrap();
{
// make a branch that conflicts with the remote branch, but doesn't know about it yet
let branch_id = controller
.create_virtual_branch(project, &BranchCreateRequest::default())
.unwrap();
fs::write(repository.path().join("file.txt"), "second").unwrap();
controller
.create_commit(project, branch_id, "second", None, false)
.unwrap();
};
{
// fetch remote
controller.update_base_branch(project).unwrap();
// just removes integrated branch
let (branches, _) = controller.list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 0);
}
}
#[test]
fn integrate_work_while_being_behind() {
let Test {
repository,
project,
controller,
..
} = &Test::default();
// make sure we have an undiscovered commit in the remote branch
{
fs::write(repository.path().join("file.txt"), "first").unwrap();
let first_commit_oid = repository.commit_all("first");
fs::write(repository.path().join("file.txt"), "second").unwrap();
repository.commit_all("second");
repository.push();
repository.reset_hard(Some(first_commit_oid));
}
controller
.set_base_branch(project, &"refs/remotes/origin/master".parse().unwrap())
.unwrap();
let branch_id = controller
.create_virtual_branch(project, &BranchCreateRequest::default())
.unwrap();
{
// open pr
fs::write(repository.path().join("file2.txt"), "new file").unwrap();
controller
.create_commit(project, branch_id, "second", None, false)
.unwrap();
controller
.push_virtual_branch(project, branch_id, false, None)
.unwrap();
}
{
// merge pr
let branch = controller.list_virtual_branches(project).unwrap().0[0].clone();
repository.merge(&branch.upstream.as_ref().unwrap().name);
repository.fetch();
}
{
// fetch remote
controller.update_base_branch(project).unwrap();
// just removes integrated branch
let (branches, _) = controller.list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 0);
}
}
// Ensure integrated branch is dropped and that a commit on another
// branch does not lead to the introduction of gost/phantom diffs.
#[test]
fn should_not_get_confused_by_commits_in_other_branches() {
let Test {
repository,
project,
controller,
..
} = &Test::default();
fs::write(repository.path().join("file-1.txt"), "one").unwrap();
let first_commit_oid = repository.commit_all("first");
fs::write(repository.path().join("file-2.txt"), "two").unwrap();
repository.commit_all("second");
repository.push();
repository.reset_hard(Some(first_commit_oid));
controller
.set_base_branch(project, &"refs/remotes/origin/master".parse().unwrap())
.unwrap();
let branch_1_id = controller
.create_virtual_branch(project, &BranchCreateRequest::default())
.unwrap();
fs::write(repository.path().join("file-3.txt"), "three").unwrap();
controller
.create_commit(project, branch_1_id, "third", None, false)
.unwrap();
let branch_2_id = controller
.create_virtual_branch(
project,
&BranchCreateRequest {
selected_for_changes: Some(true),
..Default::default()
},
)
.unwrap();
fs::write(repository.path().join("file-4.txt"), "four").unwrap();
controller
.create_commit(project, branch_2_id, "fourth", None, false)
.unwrap();
controller
.push_virtual_branch(project, branch_2_id, false, None)
.unwrap();
let branch = controller.list_virtual_branches(project).unwrap().0[1].clone();
repository.merge(&branch.upstream.as_ref().unwrap().name);
repository.fetch();
// TODO(mg): Figure out why test fails without listing first.
controller.list_virtual_branches(project).unwrap();
controller.update_base_branch(project).unwrap();
// Verify we have only the first branch left, and that no files
// are present.
let (branches, _) = controller.list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 1);
assert_eq!(branches[0].files.len(), 0);
}
}