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:
parent
720677c7f3
commit
c93e806265
1 changed files with 67 additions and 1 deletions
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue