fix: clarify conflict pane roles and status indicators

Use Resolution and Other version borders, omit branch/path metadata,
and show unsaved output state only on the writable pane. Track native
explorer conflict C from authoritative jj state across draft/check/error
transitions and clear it only after confirmed resolution.

Focused resolver and save tests pass; live terminal labels and explorer
verified without saving the mock conflicts. Full library run: 795 pass,
one unrelated async plugin fixture_barrier startup failure.
This commit is contained in:
Valdemar Lorenzen
2026-10-15 10:50:22 +02:00
parent 168e12160a
commit 5396968b08
5 changed files with 265 additions and 66 deletions
+18
View File
@@ -101,6 +101,7 @@ pub struct FilePicker {
tree_searching: bool,
warning: Option<String>,
repository_changes: Vec<WorkingFileChange>,
conflicted_paths: HashSet<PathBuf>,
has_virtual_entries: bool,
}
@@ -306,6 +307,7 @@ impl FilePicker {
tree_searching: false,
warning,
repository_changes: Vec::new(),
conflicted_paths: HashSet::new(),
};
for root in roots {
let tree = picker.compact(root, None);
@@ -917,12 +919,28 @@ impl FilePicker {
topology_changed || metadata_changed
}
/// Last authoritative conflict state, independent of ordinary change status.
pub fn is_conflicted(&self, path: &Path) -> bool {
self.conflicted_paths.contains(path)
}
pub(crate) fn set_conflicted(&mut self, path: &Path, conflicted: bool) {
if conflicted {
if !self.conflicted_paths.contains(path) {
self.conflicted_paths.insert(path.to_owned());
}
} else {
self.conflicted_paths.remove(path);
}
}
pub(crate) fn replace_paths(&mut self, paths: impl IntoIterator<Item = (usize, PathBuf)>) {
self.replace_catalog(Self::from_paths(self.root.clone(), paths));
}
fn replace_catalog(&mut self, mut replacement: Self) {
replacement.presentation = self.presentation;
replacement.conflicted_paths = std::mem::take(&mut self.conflicted_paths);
let by_path: HashMap<_, _> = replacement
.nodes
.iter()