ok/jj
1
0
Fork 0
forked from mirrors/jj

merge-tools: make :builtin materialize conflicts

This make :builtin render conflicts as conflict markers instead of
panicking. To support conflicts properly, we also need to parse the
conflict markers (calling `update_from_content()`) after the user
closes the editor.
This commit is contained in:
Martin von Zweigbergk 2024-02-27 10:30:45 -08:00 committed by Martin von Zweigbergk
parent aa79582092
commit bce8cb901f

View file

@ -2,9 +2,10 @@ use std::borrow::Cow;
use std::path::Path; use std::path::Path;
use std::sync::Arc; use std::sync::Arc;
use futures::{StreamExt, TryStreamExt}; use futures::{StreamExt, TryFutureExt, TryStreamExt};
use itertools::Itertools; use itertools::Itertools;
use jj_lib::backend::{BackendError, FileId, MergedTreeId, TreeValue}; use jj_lib::backend::{BackendError, FileId, MergedTreeId, TreeValue};
use jj_lib::conflicts::{materialize_tree_value, MaterializedTreeValue};
use jj_lib::diff::{find_line_ranges, Diff, DiffHunk}; use jj_lib::diff::{find_line_ranges, Diff, DiffHunk};
use jj_lib::files::{self, ContentHunk, MergeResult}; use jj_lib::files::{self, ContentHunk, MergeResult};
use jj_lib::matchers::Matcher; use jj_lib::matchers::Matcher;
@ -106,16 +107,21 @@ fn read_file_contents(
tree: &MergedTree, tree: &MergedTree,
path: &RepoPath, path: &RepoPath,
) -> Result<FileInfo, BuiltinToolError> { ) -> Result<FileInfo, BuiltinToolError> {
match tree.path_value(path).into_resolved() { let value = tree.path_value(path);
Ok(None) => Ok(FileInfo { let materialized_value = materialize_tree_value(store, path, value)
.map_err(BuiltinToolError::BackendError)
.block_on()?;
match materialized_value {
MaterializedTreeValue::Absent => Ok(FileInfo {
file_mode: scm_record::FileMode::absent(), file_mode: scm_record::FileMode::absent(),
contents: FileContents::Absent, contents: FileContents::Absent,
}), }),
Ok(Some(TreeValue::File { id, executable })) => { MaterializedTreeValue::File {
let mut reader = store id,
.read_file(path, &id) executable,
.map_err(BuiltinToolError::ReadFileBackend)?; mut reader,
} => {
let mut buf = Vec::new(); let mut buf = Vec::new();
reader reader
.read_to_end(&mut buf) .read_to_end(&mut buf)
@ -137,34 +143,33 @@ fn read_file_contents(
}) })
} }
Ok(Some(TreeValue::Symlink(id))) => { MaterializedTreeValue::Symlink { id, target } => {
let value = store
.read_symlink(path, &id)
.map_err(BuiltinToolError::ReadSymlink)?;
let file_mode = scm_record::FileMode(mode::SYMLINK); let file_mode = scm_record::FileMode(mode::SYMLINK);
let num_bytes = value.len().try_into().unwrap(); let num_bytes = target.len().try_into().unwrap();
Ok(FileInfo { Ok(FileInfo {
file_mode, file_mode,
contents: FileContents::Text { contents: FileContents::Text {
contents: value, contents: target,
hash: Some(id.hex()), hash: Some(id.hex()),
num_bytes, num_bytes,
}, },
}) })
} }
Ok(Some(TreeValue::Tree(tree_id))) => { MaterializedTreeValue::Tree(tree_id) => {
unreachable!("list of changed files included a tree: {tree_id:?}"); unreachable!("list of changed files included a tree: {tree_id:?}");
} }
Ok(Some(TreeValue::GitSubmodule(id))) => Err(BuiltinToolError::Unimplemented { MaterializedTreeValue::GitSubmodule(id) => Err(BuiltinToolError::Unimplemented {
item: "git submodule", item: "git submodule",
id: id.hex(), id: id.hex(),
}), }),
Ok(Some(TreeValue::Conflict(id))) => { MaterializedTreeValue::Conflict { id: _, contents } => {
unreachable!("list of changed files included a conflict: {id:?}"); // TODO: Render the ID somehow?
} let contents = buf_to_file_contents(None, contents);
Err(merge) => { Ok(FileInfo {
unreachable!("list of changed files included a merge: {merge:?}"); file_mode: scm_record::FileMode(mode::NORMAL),
contents,
})
} }
} }
} }