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

conflicts: make materialized tree/file conflicts etc a little more useful

When there are conflicts between different types of tree entries, we
currently materialize them as "Unresolved complex conflict.". This
change makes it so we mention what types were involved and what their
ids were (though we still don't have an easy way of resolving an id).
This commit is contained in:
Martin von Zweigbergk 2021-06-26 21:41:25 -07:00
parent 720677c7f3
commit c93e806265

View file

@ -14,17 +14,83 @@
use std::io::{Cursor, Write};
use itertools::Itertools;
use crate::files;
use crate::repo_path::RepoPath;
use crate::store::{Conflict, TreeValue};
use crate::store::{Conflict, ConflictPart, TreeValue};
use crate::store_wrapper::StoreWrapper;
fn describe_conflict_part(part: &ConflictPart) -> String {
match &part.value {
TreeValue::Normal {
id,
executable: false,
} => {
format!("file with id {}", id.hex())
}
TreeValue::Normal {
id,
executable: true,
} => {
format!("executable file with id {}", id.hex())
}
TreeValue::Symlink(id) => {
format!("symlink with id {}", id.hex())
}
TreeValue::Tree(id) => {
format!("tree with id {}", id.hex())
}
TreeValue::GitSubmodule(id) => {
format!("Git submodule with id {}", id.hex())
}
TreeValue::Conflict(id) => {
format!("Conflict with id {}", id.hex())
}
}
}
fn describe_conflict(conflict: &Conflict, file: &mut dyn Write) -> std::io::Result<()> {
file.write_all(b"Conflict:\n")?;
for part in &conflict.removes {
file.write_all(format!(" Removing {}\n", describe_conflict_part(part)).as_bytes())?;
}
for part in &conflict.adds {
file.write_all(format!(" Adding {}\n", describe_conflict_part(part)).as_bytes())?;
}
Ok(())
}
fn file_parts(parts: &[ConflictPart]) -> Vec<&ConflictPart> {
parts
.iter()
.filter(|part| {
matches!(
part.value,
TreeValue::Normal {
executable: false,
..
}
)
})
.collect_vec()
}
pub fn materialize_conflict(
store: &StoreWrapper,
path: &RepoPath,
conflict: &Conflict,
file: &mut dyn Write,
) {
let file_adds = file_parts(&conflict.adds);
let file_removes = file_parts(&conflict.removes);
if file_adds.len() != conflict.adds.len() || file_removes.len() != conflict.removes.len() {
// Unless all parts are regular files, we can't do much better than to try to
// describe the conflict.
describe_conflict(conflict, file).unwrap();
return;
}
match conflict.to_three_way() {
None => {
file.write_all(b"Unresolved complex conflict.\n").unwrap();