diff --git a/lib/src/default_revset_engine.rs b/lib/src/default_revset_engine.rs index dded65933..961fee3b2 100644 --- a/lib/src/default_revset_engine.rs +++ b/lib/src/default_revset_engine.rs @@ -890,7 +890,7 @@ fn has_diff_from_parent( return false; } } - let from_tree = rewrite::merge_commit_trees_without_repo(store, &index, &parents); + let from_tree = rewrite::merge_commit_trees_without_repo(store, &index, &parents).unwrap(); let to_tree = commit.tree(); from_tree.diff(&to_tree, matcher).next().is_some() } diff --git a/lib/src/repo.rs b/lib/src/repo.rs index d2fa97199..5c56c6e47 100644 --- a/lib/src/repo.rs +++ b/lib/src/repo.rs @@ -46,6 +46,7 @@ use crate::simple_op_store::SimpleOpStore; use crate::store::Store; use crate::submodule_store::SubmoduleStore; use crate::transaction::Transaction; +use crate::tree::TreeMergeError; use crate::view::{RefName, View}; use crate::{backend, dag_walk, op_store}; @@ -291,7 +292,7 @@ impl ReadonlyRepo { pub fn reload_at_head( &self, user_settings: &UserSettings, - ) -> Result, OpHeadResolutionError> { + ) -> Result, OpHeadResolutionError> { self.loader().load_at_head(user_settings) } @@ -642,7 +643,7 @@ impl RepoLoader { pub fn load_at_head( &self, user_settings: &UserSettings, - ) -> Result, OpHeadResolutionError> { + ) -> Result, OpHeadResolutionError> { let op = op_heads_store::resolve_op_heads( self.op_heads_store.as_ref(), &self.op_store, @@ -683,7 +684,7 @@ impl RepoLoader { &self, op_heads: Vec, user_settings: &UserSettings, - ) -> Result { + ) -> Result { let base_repo = self.load_at(&op_heads[0]); let mut tx = base_repo.start_transaction(user_settings, "resolve concurrent operations"); for other_op_head in op_heads.into_iter().skip(1) { @@ -834,7 +835,7 @@ impl MutableRepo { ) } - pub fn rebase_descendants(&mut self, settings: &UserSettings) -> Result { + pub fn rebase_descendants(&mut self, settings: &UserSettings) -> Result { if !self.has_rewrites() { // Optimization return Ok(0); diff --git a/lib/src/rewrite.rs b/lib/src/rewrite.rs index f199957ca..791524d57 100644 --- a/lib/src/rewrite.rs +++ b/lib/src/rewrite.rs @@ -17,7 +17,7 @@ use std::sync::Arc; use itertools::{process_results, Itertools}; -use crate::backend::{BackendError, BackendResult, CommitId, ObjectId}; +use crate::backend::{BackendError, CommitId, ObjectId}; use crate::commit::Commit; use crate::dag_walk; use crate::index::Index; @@ -27,10 +27,10 @@ use crate::repo_path::RepoPath; use crate::revset::{RevsetExpression, RevsetIteratorExt}; use crate::settings::UserSettings; use crate::store::Store; -use crate::tree::{merge_trees, Tree}; +use crate::tree::{merge_trees, Tree, TreeMergeError}; use crate::view::RefName; -pub fn merge_commit_trees(repo: &dyn Repo, commits: &[Commit]) -> Tree { +pub fn merge_commit_trees(repo: &dyn Repo, commits: &[Commit]) -> Result { merge_commit_trees_without_repo(repo.store(), repo.index(), commits) } @@ -38,11 +38,9 @@ pub fn merge_commit_trees_without_repo( store: &Arc, index: &dyn Index, commits: &[Commit], -) -> Tree { +) -> Result { if commits.is_empty() { - store - .get_tree(&RepoPath::root(), store.empty_tree_id()) - .unwrap() + Ok(store.get_tree(&RepoPath::root(), store.empty_tree_id())?) } else { let mut new_tree = commits[0].tree(); let commit_ids = commits @@ -51,15 +49,15 @@ pub fn merge_commit_trees_without_repo( .collect_vec(); for (i, other_commit) in commits.iter().enumerate().skip(1) { let ancestor_ids = index.common_ancestors(&commit_ids[0..i], &[commit_ids[i].clone()]); - let ancestors = ancestor_ids + let ancestors: Vec<_> = ancestor_ids .iter() - .map(|id| store.get_commit(id).unwrap()) - .collect_vec(); - let ancestor_tree = merge_commit_trees_without_repo(store, index, &ancestors); - let new_tree_id = merge_trees(&new_tree, &ancestor_tree, &other_commit.tree()).unwrap(); - new_tree = store.get_tree(&RepoPath::root(), &new_tree_id).unwrap(); + .map(|id| store.get_commit(id)) + .try_collect()?; + let ancestor_tree = merge_commit_trees_without_repo(store, index, &ancestors)?; + let new_tree_id = merge_trees(&new_tree, &ancestor_tree, &other_commit.tree())?; + new_tree = store.get_tree(&RepoPath::root(), &new_tree_id)?; } - new_tree + Ok(new_tree) } } @@ -68,7 +66,7 @@ pub fn rebase_commit( mut_repo: &mut MutableRepo, old_commit: &Commit, new_parents: &[Commit], -) -> BackendResult { +) -> Result { let old_parents = old_commit.parents(); let old_parent_trees = old_parents .iter() @@ -82,20 +80,20 @@ pub fn rebase_commit( // Optimization old_commit.tree_id().clone() } else { - let old_base_tree = merge_commit_trees(mut_repo, &old_parents); - let new_base_tree = merge_commit_trees(mut_repo, new_parents); + let old_base_tree = merge_commit_trees(mut_repo, &old_parents)?; + let new_base_tree = merge_commit_trees(mut_repo, new_parents)?; // TODO: pass in labels for the merge parts - merge_trees(&new_base_tree, &old_base_tree, &old_commit.tree()).unwrap() + merge_trees(&new_base_tree, &old_base_tree, &old_commit.tree())? }; let new_parent_ids = new_parents .iter() .map(|commit| commit.id().clone()) .collect(); - mut_repo + Ok(mut_repo .rewrite_commit(settings, old_commit) .set_parents(new_parent_ids) .set_tree(new_tree_id) - .write() + .write()?) } pub fn back_out_commit( @@ -103,9 +101,9 @@ pub fn back_out_commit( mut_repo: &mut MutableRepo, old_commit: &Commit, new_parents: &[Commit], -) -> BackendResult { - let old_base_tree = merge_commit_trees(mut_repo, &old_commit.parents()); - let new_base_tree = merge_commit_trees(mut_repo, new_parents); +) -> Result { + let old_base_tree = merge_commit_trees(mut_repo, &old_commit.parents())?; + let new_base_tree = merge_commit_trees(mut_repo, new_parents)?; // TODO: pass in labels for the merge parts let new_tree_id = merge_trees(&new_base_tree, &old_commit.tree(), &old_base_tree).unwrap(); let new_parent_ids = new_parents @@ -113,10 +111,10 @@ pub fn back_out_commit( .map(|commit| commit.id().clone()) .collect(); // TODO: i18n the description based on repo language - mut_repo + Ok(mut_repo .new_commit(settings, new_parent_ids, new_tree_id) .set_description(format!("backout of commit {}", &old_commit.id().hex())) - .write() + .write()?) } /// Rebases descendants of a commit onto a new commit (or several). @@ -377,7 +375,7 @@ impl<'settings, 'repo> DescendantRebaser<'settings, 'repo> { // TODO: Perhaps change the interface since it's not just about rebasing // commits. - pub fn rebase_next(&mut self) -> Result, BackendError> { + pub fn rebase_next(&mut self) -> Result, TreeMergeError> { while let Some(old_commit) = self.to_visit.pop() { let old_commit_id = old_commit.id().clone(); if let Some(new_parent_ids) = self.new_parents.get(&old_commit_id).cloned() { @@ -450,7 +448,7 @@ impl<'settings, 'repo> DescendantRebaser<'settings, 'repo> { Ok(None) } - pub fn rebase_all(&mut self) -> Result<(), BackendError> { + pub fn rebase_all(&mut self) -> Result<(), TreeMergeError> { while self.rebase_next()?.is_some() {} Ok(()) } diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 1a08ccfcb..0cf50fa0a 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1403,7 +1403,7 @@ fn cmd_diff(ui: &mut Ui, command: &CommandHelper, args: &DiffArgs) -> Result<(), let commit = workspace_command.resolve_single_rev(args.revision.as_deref().unwrap_or("@"))?; let parents = commit.parents(); - from_tree = merge_commit_trees(workspace_command.repo().as_ref(), &parents); + from_tree = merge_commit_trees(workspace_command.repo().as_ref(), &parents)?; to_tree = commit.tree() } let matcher = workspace_command.matcher_from_values(&args.paths)?; @@ -1512,7 +1512,7 @@ fn cmd_status( } if let Some(wc_commit) = &maybe_wc_commit { - let parent_tree = merge_commit_trees(repo.as_ref(), &wc_commit.parents()); + let parent_tree = merge_commit_trees(repo.as_ref(), &wc_commit.parents())?; let tree = wc_commit.tree(); if tree.id() == parent_tree.id() { formatter.write_str("The working copy is clean\n")?; @@ -1829,9 +1829,9 @@ fn rebase_to_dest_parent( Ok(source.tree()) } else { let destination_parent_tree = - merge_commit_trees(workspace_command.repo().as_ref(), &destination.parents()); + merge_commit_trees(workspace_command.repo().as_ref(), &destination.parents())?; let source_parent_tree = - merge_commit_trees(workspace_command.repo().as_ref(), &source.parents()); + merge_commit_trees(workspace_command.repo().as_ref(), &source.parents())?; let rebased_tree_id = merge_trees( &destination_parent_tree, &source_parent_tree, @@ -2229,7 +2229,7 @@ fn cmd_new(ui: &mut Ui, command: &CommandHelper, args: &NewArgs) -> Result<(), C if new_parents_commits.len() > 1 { new_parents_commits.retain(|c| c != &root_commit); } - let merged_tree = merge_commit_trees(tx.repo(), &new_parents_commits); + let merged_tree = merge_commit_trees(tx.repo(), &new_parents_commits)?; let new_parents_commit_id = new_parents_commits.iter().map(|c| c.id().clone()).collect(); new_commit = tx .mut_repo() @@ -2250,7 +2250,7 @@ fn cmd_new(ui: &mut Ui, command: &CommandHelper, args: &NewArgs) -> Result<(), C )?; } } else { - let merged_tree = merge_commit_trees(tx.repo(), &target_commits); + let merged_tree = merge_commit_trees(tx.repo(), &target_commits)?; new_commit = tx .mut_repo() .new_commit( @@ -2344,7 +2344,7 @@ fn cmd_move(ui: &mut Ui, command: &CommandHelper, args: &MoveArgs) -> Result<(), source.id().hex(), destination.id().hex() )); - let parent_tree = merge_commit_trees(tx.repo(), &source.parents()); + let parent_tree = merge_commit_trees(tx.repo(), &source.parents())?; let source_tree = source.tree(); let instructions = format!( "\ @@ -2521,7 +2521,7 @@ fn cmd_unsquash( workspace_command.check_rewritable(parent)?; let mut tx = workspace_command.start_transaction(&format!("unsquash commit {}", commit.id().hex())); - let parent_base_tree = merge_commit_trees(tx.repo(), &parent.parents()); + let parent_base_tree = merge_commit_trees(tx.repo(), &parent.parents())?; let new_parent_tree_id; if args.interactive { let instructions = format!( @@ -2831,7 +2831,7 @@ fn cmd_restore( .tree(); } else { to_commit = workspace_command.resolve_single_rev("@")?; - from_tree = merge_commit_trees(workspace_command.repo().as_ref(), &to_commit.parents()); + from_tree = merge_commit_trees(workspace_command.repo().as_ref(), &to_commit.parents())?; } workspace_command.check_rewritable(&to_commit)?; @@ -2909,7 +2909,7 @@ Adjust the right side until it shows the contents you want. If you don't make any changes, then the operation will be aborted.", tx.format_commit_summary(&target_commit), ); - let base_tree = merge_commit_trees(tx.repo(), base_commits.as_slice()); + let base_tree = merge_commit_trees(tx.repo(), base_commits.as_slice())?; let tree_id = tx.edit_diff(ui, &base_tree, &target_commit.tree(), &instructions)?; if &tree_id == target_commit.tree_id() { ui.write("Nothing changed.\n")?; @@ -2984,7 +2984,7 @@ fn cmd_split(ui: &mut Ui, command: &CommandHelper, args: &SplitArgs) -> Result<( let matcher = workspace_command.matcher_from_values(&args.paths)?; let mut tx = workspace_command.start_transaction(&format!("split commit {}", commit.id().hex())); - let base_tree = merge_commit_trees(tx.repo(), &commit.parents()); + let base_tree = merge_commit_trees(tx.repo(), &commit.parents())?; let interactive = args.paths.is_empty(); let instructions = format!( "\ diff --git a/src/commit_templater.rs b/src/commit_templater.rs index 7e38a4d4a..0832a6253 100644 --- a/src/commit_templater.rs +++ b/src/commit_templater.rs @@ -258,7 +258,8 @@ fn build_commit_keyword_opt<'repo>( language.wrap_boolean(wrap_fn(property, |commit| commit.tree().has_conflict())) } "empty" => language.wrap_boolean(wrap_fn(property, |commit| { - commit.tree().id() == rewrite::merge_commit_trees(repo, &commit.parents()).id() + let parent_tree = rewrite::merge_commit_trees(repo, &commit.parents()).unwrap(); + commit.tree().id() == parent_tree.id() })), _ => return None, }; diff --git a/src/diff_util.rs b/src/diff_util.rs index 5285517a0..68f77f638 100644 --- a/src/diff_util.rs +++ b/src/diff_util.rs @@ -154,7 +154,7 @@ pub fn show_patch( formats: &[DiffFormat], ) -> Result<(), CommandError> { let parents = commit.parents(); - let from_tree = rewrite::merge_commit_trees(workspace_command.repo().as_ref(), &parents); + let from_tree = rewrite::merge_commit_trees(workspace_command.repo().as_ref(), &parents)?; let to_tree = commit.tree(); show_diff( formatter,