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:
parent
aa79582092
commit
bce8cb901f
1 changed files with 25 additions and 20 deletions
|
@ -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,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue