Skip to content

Commit 7587340

Browse files
authored
Fix a bug that interfered with sorting of conflicted paths in the git panel (#29534)
This PR updates the git store to not register a change in a repository's merge heads until conflicted paths are seen. We currently use the repository's merge heads only to decide when the list of conflicted paths should be refreshed. Previously, the logic looked like this: - Whenever we see a change in the merge heads, set the list of conflicted paths by filtering the output of `git status`. It turns out that when a conflicting merge takes a while, we can see this sequence of events: 1. We get an event in .git and reload statuses and merge heads. Previously there were no merge heads, and now we have some, but git hasn't finished figuring out which paths have conflicts, so we set the list of conflicted paths to `[]`. 2. Git finishes computing the list of conflicted paths, and we run another scan that picks these up from `git status`, but then we throw them away because the merge heads are the same as in (1). By not updating our stored merge heads until we see some conflicts in `git status`, we delay this step until (2), and so the conflicted paths show up in the git panel as intended. This means that our merge heads state no longer matches what's on disk (in particular, during a clean merge we'll never update them at all), but that's okay because we only keep this state for the purpose of organizing conflicts. Release Notes: - Fixed a bug that could cause conflicted paths to not appear in their own section in the git panel.
1 parent 5073cba commit 7587340

File tree

1 file changed

+27
-2
lines changed

1 file changed

+27
-2
lines changed

crates/project/src/git_store.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2692,6 +2692,7 @@ impl MergeDetails {
26922692
status: &SumTree<StatusEntry>,
26932693
prev_snapshot: &RepositorySnapshot,
26942694
) -> Result<(MergeDetails, bool)> {
2695+
log::debug!("load merge details");
26952696
let message = backend.merge_message().await;
26962697
let heads = backend
26972698
.revparse_batch(vec![
@@ -2709,12 +2710,33 @@ impl MergeDetails {
27092710
.collect::<Vec<_>>();
27102711
let merge_heads_changed = heads != prev_snapshot.merge.heads;
27112712
let conflicted_paths = if merge_heads_changed {
2712-
TreeSet::from_ordered_entries(
2713+
let current_conflicted_paths = TreeSet::from_ordered_entries(
27132714
status
27142715
.iter()
27152716
.filter(|entry| entry.status.is_conflicted())
27162717
.map(|entry| entry.repo_path.clone()),
2717-
)
2718+
);
2719+
2720+
// It can happen that we run a scan while a lengthy merge is in progress
2721+
// that will eventually result in conflicts, but before those conflicts
2722+
// are reported by `git status`. Since for the moment we only care about
2723+
// the merge heads state for the purposes of tracking conflicts, don't update
2724+
// this state until we see some conflicts.
2725+
if heads.iter().any(Option::is_some)
2726+
&& !prev_snapshot.merge.heads.iter().any(Option::is_some)
2727+
&& current_conflicted_paths.is_empty()
2728+
{
2729+
log::debug!("not updating merge heads because no conflicts found");
2730+
return Ok((
2731+
MergeDetails {
2732+
message: message.map(SharedString::from),
2733+
..prev_snapshot.merge.clone()
2734+
},
2735+
false,
2736+
));
2737+
}
2738+
2739+
current_conflicted_paths
27182740
} else {
27192741
prev_snapshot.merge.conflicted_paths.clone()
27202742
};
@@ -3998,6 +4020,8 @@ impl Repository {
39984020
Some(GitJobKey::ReloadGitState),
39994021
None,
40004022
|state, mut cx| async move {
4023+
log::debug!("run scheduled git status scan");
4024+
40014025
let Some(this) = this.upgrade() else {
40024026
return Ok(());
40034027
};
@@ -4535,6 +4559,7 @@ async fn compute_snapshot(
45354559
);
45364560
let (merge_details, merge_heads_changed) =
45374561
MergeDetails::load(&backend, &statuses_by_path, &prev_snapshot).await?;
4562+
log::debug!("new merge details (changed={merge_heads_changed:?}): {merge_details:?}");
45384563

45394564
if merge_heads_changed
45404565
|| branch != prev_snapshot.branch

0 commit comments

Comments
 (0)