mirror of
https://github.com/martinvonz/jj.git
synced 2024-12-28 07:20:11 +00:00
squash: move updating of source commits out of diff-editing loop
This is just a little refactoring to prepare for using `transform_descendants()`.
This commit is contained in:
parent
7319479df9
commit
2bd2358d6a
1 changed files with 42 additions and 22 deletions
|
@ -15,6 +15,7 @@
|
|||
use itertools::Itertools as _;
|
||||
use jj_lib::commit::{Commit, CommitIteratorExt};
|
||||
use jj_lib::matchers::Matcher;
|
||||
use jj_lib::merged_tree::MergedTree;
|
||||
use jj_lib::object_id::ObjectId;
|
||||
use jj_lib::repo::Repo;
|
||||
use jj_lib::revset;
|
||||
|
@ -181,9 +182,14 @@ pub fn move_diff(
|
|||
) -> Result<(), CommandError> {
|
||||
tx.base_workspace_helper()
|
||||
.check_rewritable(sources.iter().chain(std::iter::once(destination)).ids())?;
|
||||
// Tree diffs to apply to the destination
|
||||
let mut tree_diffs = vec![];
|
||||
let mut abandoned_commits = vec![];
|
||||
|
||||
struct SourceCommit<'a> {
|
||||
commit: &'a Commit,
|
||||
parent_tree: MergedTree,
|
||||
selected_tree: MergedTree,
|
||||
abandon: bool,
|
||||
}
|
||||
let mut source_commits = vec![];
|
||||
for source in sources {
|
||||
let parent_tree = merge_commit_trees(tx.repo(), &source.parents())?;
|
||||
let source_tree = source.tree()?;
|
||||
|
@ -206,26 +212,20 @@ from the source will be moved into the destination.
|
|||
let selected_tree_id =
|
||||
diff_selector.select(&parent_tree, &source_tree, matcher, Some(&instructions))?;
|
||||
let selected_tree = tx.repo().store().get_root_tree(&selected_tree_id)?;
|
||||
let abandon_source = selected_tree.id() == source_tree.id();
|
||||
let abandon = selected_tree.id() == source_tree.id();
|
||||
// TODO: Do we want to optimize the case of moving to the parent commit (`jj
|
||||
// squash -r`)? The source tree will be unchanged in that case.
|
||||
|
||||
// Apply the reverse of the selected changes onto the source
|
||||
let new_source_tree = source_tree.merge(&selected_tree, &parent_tree)?;
|
||||
if abandon_source {
|
||||
abandoned_commits.push(source);
|
||||
tx.mut_repo().record_abandoned_commit(source.id().clone());
|
||||
} else {
|
||||
tx.mut_repo()
|
||||
.rewrite_commit(settings, source)
|
||||
.set_tree_id(new_source_tree.id().clone())
|
||||
.write()?;
|
||||
}
|
||||
if selected_tree_id != parent_tree.id() {
|
||||
tree_diffs.push((parent_tree, selected_tree));
|
||||
}
|
||||
source_commits.push(SourceCommit {
|
||||
commit: source,
|
||||
parent_tree,
|
||||
selected_tree,
|
||||
abandon,
|
||||
});
|
||||
}
|
||||
if tree_diffs.is_empty() {
|
||||
if source_commits
|
||||
.iter()
|
||||
.all(|source| source.selected_tree == source.parent_tree)
|
||||
{
|
||||
if diff_selector.is_interactive() {
|
||||
return Err(user_error("No changes selected"));
|
||||
}
|
||||
|
@ -246,6 +246,22 @@ from the source will be moved into the destination.
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
for source in &source_commits {
|
||||
if source.abandon {
|
||||
tx.mut_repo()
|
||||
.record_abandoned_commit(source.commit.id().clone());
|
||||
} else {
|
||||
let source_tree = source.commit.tree()?;
|
||||
// Apply the reverse of the selected changes onto the source
|
||||
let new_source_tree = source_tree.merge(&source.selected_tree, &source.parent_tree)?;
|
||||
tx.mut_repo()
|
||||
.rewrite_commit(settings, source.commit)
|
||||
.set_tree_id(new_source_tree.id().clone())
|
||||
.write()?;
|
||||
}
|
||||
}
|
||||
|
||||
let mut rewritten_destination = destination.clone();
|
||||
if sources
|
||||
.iter()
|
||||
|
@ -261,13 +277,17 @@ from the source will be moved into the destination.
|
|||
}
|
||||
// Apply the selected changes onto the destination
|
||||
let mut destination_tree = rewritten_destination.tree()?;
|
||||
for (tree1, tree2) in tree_diffs {
|
||||
destination_tree = destination_tree.merge(&tree1, &tree2)?;
|
||||
for source in &source_commits {
|
||||
destination_tree = destination_tree.merge(&source.parent_tree, &source.selected_tree)?;
|
||||
}
|
||||
let description = match description {
|
||||
SquashedDescription::Exact(description) => description,
|
||||
SquashedDescription::UseDestination => destination.description().to_owned(),
|
||||
SquashedDescription::Combine => {
|
||||
let abandoned_commits = source_commits
|
||||
.iter()
|
||||
.filter_map(|source| source.abandon.then_some(source.commit))
|
||||
.collect_vec();
|
||||
combine_messages(tx.base_repo(), &abandoned_commits, destination, settings)?
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue