git: Add CHERRY_PICK_HEAD to the list of merge heads (#26145)
Attempt to fix an issue where conflicts from a cherry-pick don't get cleared out of the git panel after being resolved. Release Notes: - Git Beta: Fixed resolution of conflicts from cherry-picks not being reflected in the git panel
This commit is contained in:
parent
431727fdd7
commit
5daadc0d30
2 changed files with 112 additions and 0 deletions
|
@ -5,6 +5,7 @@ use crate::{
|
|||
use anyhow::Result;
|
||||
use fs::{FakeFs, Fs, RealFs, RemoveOptions};
|
||||
use git::{
|
||||
repository::RepoPath,
|
||||
status::{
|
||||
FileStatus, GitSummary, StatusCode, TrackedStatus, TrackedSummary, UnmergedStatus,
|
||||
UnmergedStatusCode,
|
||||
|
@ -3307,6 +3308,87 @@ async fn test_propagate_statuses_for_nested_repos(cx: &mut TestAppContext) {
|
|||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_conflicted_cherry_pick(cx: &mut TestAppContext) {
|
||||
init_test(cx);
|
||||
cx.executor().allow_parking();
|
||||
|
||||
let root = TempTree::new(json!({
|
||||
"project": {
|
||||
"a.txt": "a",
|
||||
},
|
||||
}));
|
||||
let root_path = root.path();
|
||||
|
||||
let tree = Worktree::local(
|
||||
root_path,
|
||||
true,
|
||||
Arc::new(RealFs::default()),
|
||||
Default::default(),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let repo = git_init(&root_path.join("project"));
|
||||
git_add("a.txt", &repo);
|
||||
git_commit("init", &repo);
|
||||
|
||||
cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete())
|
||||
.await;
|
||||
|
||||
tree.flush_fs_events(cx).await;
|
||||
|
||||
git_branch("other-branch", &repo);
|
||||
git_checkout("refs/heads/other-branch", &repo);
|
||||
std::fs::write(root_path.join("project/a.txt"), "A").unwrap();
|
||||
git_add("a.txt", &repo);
|
||||
git_commit("capitalize", &repo);
|
||||
let commit = repo
|
||||
.head()
|
||||
.expect("Failed to get HEAD")
|
||||
.peel_to_commit()
|
||||
.expect("HEAD is not a commit");
|
||||
git_checkout("refs/heads/master", &repo);
|
||||
std::fs::write(root_path.join("project/a.txt"), "b").unwrap();
|
||||
git_add("a.txt", &repo);
|
||||
git_commit("improve letter", &repo);
|
||||
git_cherry_pick(&commit, &repo);
|
||||
std::fs::read_to_string(root_path.join("project/.git/CHERRY_PICK_HEAD"))
|
||||
.expect("No CHERRY_PICK_HEAD");
|
||||
pretty_assertions::assert_eq!(
|
||||
git_status(&repo),
|
||||
collections::HashMap::from_iter([("a.txt".to_owned(), git2::Status::CONFLICTED)])
|
||||
);
|
||||
tree.flush_fs_events(cx).await;
|
||||
let conflicts = tree.update(cx, |tree, _| {
|
||||
let entry = tree.git_entries().nth(0).expect("No git entry").clone();
|
||||
entry
|
||||
.current_merge_conflicts
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
pretty_assertions::assert_eq!(conflicts, [RepoPath::from("a.txt")]);
|
||||
|
||||
git_add("a.txt", &repo);
|
||||
// Attempt to manually simulate what `git cherry-pick --continue` would do.
|
||||
git_commit("whatevs", &repo);
|
||||
std::fs::remove_file(root.path().join("project/.git/CHERRY_PICK_HEAD"))
|
||||
.expect("Failed to remove CHERRY_PICK_HEAD");
|
||||
pretty_assertions::assert_eq!(git_status(&repo), collections::HashMap::default());
|
||||
tree.flush_fs_events(cx).await;
|
||||
let conflicts = tree.update(cx, |tree, _| {
|
||||
let entry = tree.git_entries().nth(0).expect("No git entry").clone();
|
||||
entry
|
||||
.current_merge_conflicts
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
pretty_assertions::assert_eq!(conflicts, []);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_private_single_file_worktree(cx: &mut TestAppContext) {
|
||||
init_test(cx);
|
||||
|
@ -3405,6 +3487,11 @@ fn git_commit(msg: &'static str, repo: &git2::Repository) {
|
|||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn git_cherry_pick(commit: &git2::Commit<'_>, repo: &git2::Repository) {
|
||||
repo.cherrypick(commit, None).expect("Failed to cherrypick");
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn git_stash(repo: &mut git2::Repository) {
|
||||
use git2::Signature;
|
||||
|
@ -3430,6 +3517,22 @@ fn git_reset(offset: usize, repo: &git2::Repository) {
|
|||
.expect("Could not reset");
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn git_branch(name: &str, repo: &git2::Repository) {
|
||||
let head = repo
|
||||
.head()
|
||||
.expect("Couldn't get repo head")
|
||||
.peel_to_commit()
|
||||
.expect("HEAD is not a commit");
|
||||
repo.branch(name, &head, false).expect("Failed to commit");
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn git_checkout(name: &str, repo: &git2::Repository) {
|
||||
repo.set_head(name).expect("Failed to set head");
|
||||
repo.checkout_head(None).expect("Failed to check out head");
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[track_caller]
|
||||
fn git_status(repo: &git2::Repository) -> collections::HashMap<String, git2::Status> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue