mirror of
https://github.com/martinvonz/jj.git
synced 2024-11-24 06:19:42 +00:00
merged_tree: propagate errors from conflict iterator
Some checks are pending
binaries / Build binary artifacts (push) Waiting to run
nix / flake check (push) Waiting to run
build / build (, macos-13) (push) Waiting to run
build / build (, macos-14) (push) Waiting to run
build / build (, ubuntu-latest) (push) Waiting to run
build / build (, windows-latest) (push) Waiting to run
build / build (--all-features, ubuntu-latest) (push) Waiting to run
build / Build jj-lib without Git support (push) Waiting to run
build / Check protos (push) Waiting to run
build / Check formatting (push) Waiting to run
build / Check that MkDocs can build the docs (push) Waiting to run
build / Check that MkDocs can build the docs with latest Python and uv (push) Waiting to run
build / cargo-deny (advisories) (push) Waiting to run
build / cargo-deny (bans licenses sources) (push) Waiting to run
build / Clippy check (push) Waiting to run
Codespell / Codespell (push) Waiting to run
website / prerelease-docs-build-deploy (ubuntu-latest) (push) Waiting to run
Scorecards supply-chain security / Scorecards analysis (push) Waiting to run
Some checks are pending
binaries / Build binary artifacts (push) Waiting to run
nix / flake check (push) Waiting to run
build / build (, macos-13) (push) Waiting to run
build / build (, macos-14) (push) Waiting to run
build / build (, ubuntu-latest) (push) Waiting to run
build / build (, windows-latest) (push) Waiting to run
build / build (--all-features, ubuntu-latest) (push) Waiting to run
build / Build jj-lib without Git support (push) Waiting to run
build / Check protos (push) Waiting to run
build / Check formatting (push) Waiting to run
build / Check that MkDocs can build the docs (push) Waiting to run
build / Check that MkDocs can build the docs with latest Python and uv (push) Waiting to run
build / cargo-deny (advisories) (push) Waiting to run
build / cargo-deny (bans licenses sources) (push) Waiting to run
build / Clippy check (push) Waiting to run
Codespell / Codespell (push) Waiting to run
website / prerelease-docs-build-deploy (ubuntu-latest) (push) Waiting to run
Scorecards supply-chain security / Scorecards analysis (push) Waiting to run
This commit is contained in:
parent
9ec216a2bb
commit
10c90a5099
3 changed files with 33 additions and 16 deletions
|
@ -51,6 +51,7 @@ use clap_complete::ArgValueCandidates;
|
|||
use indexmap::IndexMap;
|
||||
use indexmap::IndexSet;
|
||||
use itertools::Itertools;
|
||||
use jj_lib::backend::BackendResult;
|
||||
use jj_lib::backend::ChangeId;
|
||||
use jj_lib::backend::CommitId;
|
||||
use jj_lib::backend::MergedTreeId;
|
||||
|
@ -2467,7 +2468,7 @@ fn update_stale_working_copy(
|
|||
|
||||
#[instrument(skip_all)]
|
||||
pub fn print_conflicted_paths(
|
||||
conflicts: Vec<(RepoPathBuf, MergedTreeValue)>,
|
||||
conflicts: Vec<(RepoPathBuf, BackendResult<MergedTreeValue>)>,
|
||||
formatter: &mut dyn Formatter,
|
||||
workspace_command: &WorkspaceCommandHelper,
|
||||
) -> Result<(), CommandError> {
|
||||
|
@ -2481,7 +2482,9 @@ pub fn print_conflicted_paths(
|
|||
.map(|p| format!("{:width$}", p, width = max_path_len.min(32) + 3));
|
||||
|
||||
for ((_, conflict), formatted_path) in std::iter::zip(conflicts, formatted_paths) {
|
||||
let conflict = conflict.simplify();
|
||||
// TODO: Display the error for the path instead of failing the whole command if
|
||||
// `conflict` is an error?
|
||||
let conflict = conflict?.simplify();
|
||||
let sides = conflict.num_sides();
|
||||
let n_adds = conflict.adds().flatten().count();
|
||||
let deletions = sides - n_adds;
|
||||
|
|
|
@ -182,7 +182,7 @@ impl MergedTree {
|
|||
/// all sides are trees, so tree/file conflicts will be reported as a single
|
||||
/// conflict, not one for each path in the tree.
|
||||
// TODO: Restrict this by a matcher (or add a separate method for that).
|
||||
pub fn conflicts(&self) -> impl Iterator<Item = (RepoPathBuf, MergedTreeValue)> {
|
||||
pub fn conflicts(&self) -> impl Iterator<Item = (RepoPathBuf, BackendResult<MergedTreeValue>)> {
|
||||
ConflictIterator::new(self)
|
||||
}
|
||||
|
||||
|
@ -651,20 +651,25 @@ impl ConflictIterator {
|
|||
}
|
||||
|
||||
impl Iterator for ConflictIterator {
|
||||
type Item = (RepoPathBuf, MergedTreeValue);
|
||||
type Item = (RepoPathBuf, BackendResult<MergedTreeValue>);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
while let Some(top) = self.stack.last_mut() {
|
||||
if let Some((path, tree_values)) = top.entries.pop() {
|
||||
// TODO: propagate errors
|
||||
if let Some(trees) = tree_values.to_tree_merge(&self.store, &path).unwrap() {
|
||||
// If all sides are trees or missing, descend into the merged tree
|
||||
self.stack.push(ConflictsDirItem::from(&trees));
|
||||
} else {
|
||||
// Otherwise this is a conflict between files, trees, etc. If they could
|
||||
// be automatically resolved, they should have been when the top-level
|
||||
// tree conflict was written, so we assume that they can't be.
|
||||
return Some((path, tree_values));
|
||||
match tree_values.to_tree_merge(&self.store, &path) {
|
||||
Ok(Some(trees)) => {
|
||||
// If all sides are trees or missing, descend into the merged tree
|
||||
self.stack.push(ConflictsDirItem::from(&trees));
|
||||
}
|
||||
Ok(None) => {
|
||||
// Otherwise this is a conflict between files, trees, etc. If they could
|
||||
// be automatically resolved, they should have been when the top-level
|
||||
// tree conflict was written, so we assume that they can't be.
|
||||
return Some((path, Ok(tree_values)));
|
||||
}
|
||||
Err(err) => {
|
||||
return Some((path, Err(err)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.stack.pop();
|
||||
|
|
|
@ -638,7 +638,10 @@ fn test_conflict_iterator() {
|
|||
vec![base1.clone()],
|
||||
vec![side1.clone(), side2.clone()],
|
||||
));
|
||||
let conflicts = tree.conflicts().collect_vec();
|
||||
let conflicts = tree
|
||||
.conflicts()
|
||||
.map(|(path, conflict)| (path, conflict.unwrap()))
|
||||
.collect_vec();
|
||||
let conflict_at = |path: &RepoPath| {
|
||||
Merge::from_removes_adds(
|
||||
vec![base1.path_value(path).unwrap()],
|
||||
|
@ -672,7 +675,10 @@ fn test_conflict_iterator() {
|
|||
|
||||
// After we resolve conflicts, there are only non-trivial conflicts left
|
||||
let tree = tree.resolve().unwrap();
|
||||
let conflicts = tree.conflicts().collect_vec();
|
||||
let conflicts = tree
|
||||
.conflicts()
|
||||
.map(|(path, conflict)| (path, conflict.unwrap()))
|
||||
.collect_vec();
|
||||
assert_eq!(
|
||||
conflicts,
|
||||
vec![
|
||||
|
@ -725,7 +731,10 @@ fn test_conflict_iterator_higher_arity() {
|
|||
vec![base1.clone(), base2.clone()],
|
||||
vec![side1.clone(), side2.clone(), side3.clone()],
|
||||
));
|
||||
let conflicts = tree.conflicts().collect_vec();
|
||||
let conflicts = tree
|
||||
.conflicts()
|
||||
.map(|(path, conflict)| (path, conflict.unwrap()))
|
||||
.collect_vec();
|
||||
let conflict_at = |path: &RepoPath| {
|
||||
Merge::from_removes_adds(
|
||||
vec![
|
||||
|
|
Loading…
Reference in a new issue