rewrite: propagate errors from merge_trees()

This commit is contained in:
Martin von Zweigbergk 2023-06-29 21:47:53 -07:00 committed by Martin von Zweigbergk
parent 134efabcef
commit b297c0c0d8
6 changed files with 45 additions and 45 deletions

View file

@ -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()
}

View file

@ -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<Arc<ReadonlyRepo>, OpHeadResolutionError<BackendError>> {
) -> Result<Arc<ReadonlyRepo>, OpHeadResolutionError<TreeMergeError>> {
self.loader().load_at_head(user_settings)
}
@ -642,7 +643,7 @@ impl RepoLoader {
pub fn load_at_head(
&self,
user_settings: &UserSettings,
) -> Result<Arc<ReadonlyRepo>, OpHeadResolutionError<BackendError>> {
) -> Result<Arc<ReadonlyRepo>, OpHeadResolutionError<TreeMergeError>> {
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<Operation>,
user_settings: &UserSettings,
) -> Result<Operation, BackendError> {
) -> Result<Operation, TreeMergeError> {
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<usize, BackendError> {
pub fn rebase_descendants(&mut self, settings: &UserSettings) -> Result<usize, TreeMergeError> {
if !self.has_rewrites() {
// Optimization
return Ok(0);

View file

@ -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<Tree, TreeMergeError> {
merge_commit_trees_without_repo(repo.store(), repo.index(), commits)
}
@ -38,11 +38,9 @@ pub fn merge_commit_trees_without_repo(
store: &Arc<Store>,
index: &dyn Index,
commits: &[Commit],
) -> Tree {
) -> Result<Tree, TreeMergeError> {
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<Commit> {
) -> Result<Commit, TreeMergeError> {
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<Commit> {
let old_base_tree = merge_commit_trees(mut_repo, &old_commit.parents());
let new_base_tree = merge_commit_trees(mut_repo, new_parents);
) -> Result<Commit, TreeMergeError> {
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<Option<RebasedDescendant>, BackendError> {
pub fn rebase_next(&mut self) -> Result<Option<RebasedDescendant>, 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(())
}

View file

@ -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!(
"\

View file

@ -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,
};

View file

@ -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,