mirror of
https://github.com/martinvonz/jj.git
synced 2025-05-20 14:43:13 +00:00
rewrite: split move_commits() into immutable/mutable parts
This makes it clear that the repo state isn't mutated during computation of the destination and descendants. Still compute_move_commits() is big, so we might want to split it further. If needed, maybe we can add variants of apply_move_commits() to fix up intermediate predecessor chains? compute_move_commits() needs (immutable) &MutableRepo because it depends on repo.find_descendants_for_rebase().
This commit is contained in:
parent
cb2944e287
commit
b9e4e4fe8a
@ -389,7 +389,6 @@ pub struct RewriteRefsOptions {
|
|||||||
pub delete_abandoned_bookmarks: bool,
|
pub delete_abandoned_bookmarks: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct MoveCommitsStats {
|
pub struct MoveCommitsStats {
|
||||||
/// The number of commits in the target set which were rebased.
|
/// The number of commits in the target set which were rebased.
|
||||||
pub num_rebased_targets: u32,
|
pub num_rebased_targets: u32,
|
||||||
@ -419,6 +418,23 @@ pub enum MoveCommitsTarget {
|
|||||||
Roots(Vec<CommitId>),
|
Roots(Vec<CommitId>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
struct ComputedMoveCommits {
|
||||||
|
target_commit_ids: IndexSet<CommitId>,
|
||||||
|
descendants: Vec<Commit>,
|
||||||
|
commit_new_parents_map: HashMap<CommitId, Vec<CommitId>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ComputedMoveCommits {
|
||||||
|
fn empty() -> Self {
|
||||||
|
ComputedMoveCommits {
|
||||||
|
target_commit_ids: IndexSet::new(),
|
||||||
|
descendants: vec![],
|
||||||
|
commit_new_parents_map: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Moves `loc.target` commits from their current location to a new location in
|
/// Moves `loc.target` commits from their current location to a new location in
|
||||||
/// the graph.
|
/// the graph.
|
||||||
///
|
///
|
||||||
@ -432,6 +448,14 @@ pub fn move_commits(
|
|||||||
loc: &MoveCommitsLocation,
|
loc: &MoveCommitsLocation,
|
||||||
options: &RebaseOptions,
|
options: &RebaseOptions,
|
||||||
) -> BackendResult<MoveCommitsStats> {
|
) -> BackendResult<MoveCommitsStats> {
|
||||||
|
let commits = compute_move_commits(mut_repo, loc)?;
|
||||||
|
apply_move_commits(mut_repo, commits, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compute_move_commits(
|
||||||
|
repo: &MutableRepo,
|
||||||
|
loc: &MoveCommitsLocation,
|
||||||
|
) -> BackendResult<ComputedMoveCommits> {
|
||||||
let target_commit_ids: IndexSet<CommitId>;
|
let target_commit_ids: IndexSet<CommitId>;
|
||||||
let connected_target_commits: Vec<Commit>;
|
let connected_target_commits: Vec<Commit>;
|
||||||
let connected_target_commits_internal_parents: HashMap<CommitId, Vec<CommitId>>;
|
let connected_target_commits_internal_parents: HashMap<CommitId, Vec<CommitId>>;
|
||||||
@ -440,17 +464,17 @@ pub fn move_commits(
|
|||||||
match &loc.target {
|
match &loc.target {
|
||||||
MoveCommitsTarget::Commits(commit_ids) => {
|
MoveCommitsTarget::Commits(commit_ids) => {
|
||||||
if commit_ids.is_empty() {
|
if commit_ids.is_empty() {
|
||||||
return Ok(MoveCommitsStats::default());
|
return Ok(ComputedMoveCommits::empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
target_commit_ids = commit_ids.iter().cloned().collect();
|
target_commit_ids = commit_ids.iter().cloned().collect();
|
||||||
|
|
||||||
connected_target_commits = RevsetExpression::commits(commit_ids.clone())
|
connected_target_commits = RevsetExpression::commits(commit_ids.clone())
|
||||||
.connected()
|
.connected()
|
||||||
.evaluate(mut_repo)
|
.evaluate(repo)
|
||||||
.map_err(|err| err.into_backend_error())?
|
.map_err(|err| err.into_backend_error())?
|
||||||
.iter()
|
.iter()
|
||||||
.commits(mut_repo.store())
|
.commits(repo.store())
|
||||||
.try_collect()
|
.try_collect()
|
||||||
.map_err(|err| err.into_backend_error())?;
|
.map_err(|err| err.into_backend_error())?;
|
||||||
connected_target_commits_internal_parents =
|
connected_target_commits_internal_parents =
|
||||||
@ -466,12 +490,12 @@ pub fn move_commits(
|
|||||||
}
|
}
|
||||||
MoveCommitsTarget::Roots(root_ids) => {
|
MoveCommitsTarget::Roots(root_ids) => {
|
||||||
if root_ids.is_empty() {
|
if root_ids.is_empty() {
|
||||||
return Ok(MoveCommitsStats::default());
|
return Ok(ComputedMoveCommits::empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
target_commit_ids = RevsetExpression::commits(root_ids.clone())
|
target_commit_ids = RevsetExpression::commits(root_ids.clone())
|
||||||
.descendants()
|
.descendants()
|
||||||
.evaluate(mut_repo)
|
.evaluate(repo)
|
||||||
.map_err(|err| err.into_backend_error())?
|
.map_err(|err| err.into_backend_error())?
|
||||||
.iter()
|
.iter()
|
||||||
.try_collect()
|
.try_collect()
|
||||||
@ -479,7 +503,7 @@ pub fn move_commits(
|
|||||||
|
|
||||||
connected_target_commits = target_commit_ids
|
connected_target_commits = target_commit_ids
|
||||||
.iter()
|
.iter()
|
||||||
.map(|id| mut_repo.store().get_commit(id))
|
.map(|id| repo.store().get_commit(id))
|
||||||
.try_collect()?;
|
.try_collect()?;
|
||||||
// We don't have to compute the internal parents for the connected target set,
|
// We don't have to compute the internal parents for the connected target set,
|
||||||
// since the connected target set is the same as the target set.
|
// since the connected target set is the same as the target set.
|
||||||
@ -493,7 +517,7 @@ pub fn move_commits(
|
|||||||
// ancestors which are not in the target set as parents.
|
// ancestors which are not in the target set as parents.
|
||||||
let mut target_commits_external_parents: HashMap<CommitId, IndexSet<CommitId>> = HashMap::new();
|
let mut target_commits_external_parents: HashMap<CommitId, IndexSet<CommitId>> = HashMap::new();
|
||||||
for id in target_commit_ids.iter().rev() {
|
for id in target_commit_ids.iter().rev() {
|
||||||
let commit = mut_repo.store().get_commit(id)?;
|
let commit = repo.store().get_commit(id)?;
|
||||||
let mut new_parents = IndexSet::new();
|
let mut new_parents = IndexSet::new();
|
||||||
for old_parent in commit.parent_ids() {
|
for old_parent in commit.parent_ids() {
|
||||||
if let Some(parents) = target_commits_external_parents.get(old_parent) {
|
if let Some(parents) = target_commits_external_parents.get(old_parent) {
|
||||||
@ -534,10 +558,10 @@ pub fn move_commits(
|
|||||||
&RevsetExpression::commits(target_commit_ids.iter().cloned().collect_vec())
|
&RevsetExpression::commits(target_commit_ids.iter().cloned().collect_vec())
|
||||||
.children(),
|
.children(),
|
||||||
)
|
)
|
||||||
.evaluate(mut_repo)
|
.evaluate(repo)
|
||||||
.map_err(|err| err.into_backend_error())?
|
.map_err(|err| err.into_backend_error())?
|
||||||
.iter()
|
.iter()
|
||||||
.commits(mut_repo.store())
|
.commits(repo.store())
|
||||||
.try_collect()
|
.try_collect()
|
||||||
.map_err(|err| err.into_backend_error())?;
|
.map_err(|err| err.into_backend_error())?;
|
||||||
|
|
||||||
@ -582,14 +606,14 @@ pub fn move_commits(
|
|||||||
if let Some(children) = target_commit_external_descendants.get(id) {
|
if let Some(children) = target_commit_external_descendants.get(id) {
|
||||||
new_children.extend(children.iter().cloned());
|
new_children.extend(children.iter().cloned());
|
||||||
} else {
|
} else {
|
||||||
new_children.push(mut_repo.store().get_commit(id)?);
|
new_children.push(repo.store().get_commit(id)?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
new_children
|
new_children
|
||||||
} else {
|
} else {
|
||||||
loc.new_child_ids
|
loc.new_child_ids
|
||||||
.iter()
|
.iter()
|
||||||
.map(|id| mut_repo.store().get_commit(id))
|
.map(|id| repo.store().get_commit(id))
|
||||||
.try_collect()?
|
.try_collect()?
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -645,8 +669,8 @@ pub fn move_commits(
|
|||||||
let mut roots = target_roots.iter().cloned().collect_vec();
|
let mut roots = target_roots.iter().cloned().collect_vec();
|
||||||
roots.extend(new_children.iter().ids().cloned());
|
roots.extend(new_children.iter().ids().cloned());
|
||||||
|
|
||||||
let descendants = mut_repo.find_descendants_for_rebase(roots.clone())?;
|
let descendants = repo.find_descendants_for_rebase(roots.clone())?;
|
||||||
let commit_new_parents_map: HashMap<_, _> = descendants
|
let commit_new_parents_map = descendants
|
||||||
.iter()
|
.iter()
|
||||||
.map(|commit| {
|
.map(|commit| {
|
||||||
let commit_id = commit.id();
|
let commit_id = commit.id();
|
||||||
@ -678,7 +702,7 @@ pub fn move_commits(
|
|||||||
connected_target_commits_internal_parents.get(parent_id) {
|
connected_target_commits_internal_parents.get(parent_id) {
|
||||||
new_parents.extend(parents.iter().cloned());
|
new_parents.extend(parents.iter().cloned());
|
||||||
} else if !new_children.iter().any(|new_child| {
|
} else if !new_children.iter().any(|new_child| {
|
||||||
mut_repo.index().is_ancestor(new_child.id(), parent_id) }) {
|
repo.index().is_ancestor(new_child.id(), parent_id) }) {
|
||||||
new_parents.push(parent_id.clone());
|
new_parents.push(parent_id.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -708,6 +732,18 @@ pub fn move_commits(
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
Ok(ComputedMoveCommits {
|
||||||
|
target_commit_ids,
|
||||||
|
descendants,
|
||||||
|
commit_new_parents_map,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_move_commits(
|
||||||
|
mut_repo: &mut MutableRepo,
|
||||||
|
commits: ComputedMoveCommits,
|
||||||
|
options: &RebaseOptions,
|
||||||
|
) -> BackendResult<MoveCommitsStats> {
|
||||||
let mut num_rebased_targets = 0;
|
let mut num_rebased_targets = 0;
|
||||||
let mut num_rebased_descendants = 0;
|
let mut num_rebased_descendants = 0;
|
||||||
let mut num_skipped_rebases = 0;
|
let mut num_skipped_rebases = 0;
|
||||||
@ -721,13 +757,13 @@ pub fn move_commits(
|
|||||||
};
|
};
|
||||||
|
|
||||||
mut_repo.transform_commits(
|
mut_repo.transform_commits(
|
||||||
descendants,
|
commits.descendants,
|
||||||
&commit_new_parents_map,
|
&commits.commit_new_parents_map,
|
||||||
&options.rewrite_refs,
|
&options.rewrite_refs,
|
||||||
|rewriter| {
|
|rewriter| {
|
||||||
let old_commit_id = rewriter.old_commit().id();
|
let old_commit_id = rewriter.old_commit().id();
|
||||||
if rewriter.parents_changed() {
|
if rewriter.parents_changed() {
|
||||||
let is_target_commit = target_commit_ids.contains(old_commit_id);
|
let is_target_commit = commits.target_commit_ids.contains(old_commit_id);
|
||||||
let rebased_commit = rebase_commit_with_options(
|
let rebased_commit = rebase_commit_with_options(
|
||||||
rewriter,
|
rewriter,
|
||||||
if is_target_commit {
|
if is_target_commit {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user