ok/jj
1
0
Fork 0
forked from mirrors/jj

rewrite: move calculation of set to rebase to MutableRepo

This lets us make `parent_mapping` private again.
This commit is contained in:
Martin von Zweigbergk 2024-04-12 09:49:38 -07:00 committed by Martin von Zweigbergk
parent 53a0e23759
commit 0bbebaf4f9
2 changed files with 47 additions and 42 deletions

View file

@ -50,7 +50,7 @@ use crate::operation::Operation;
use crate::refs::{ use crate::refs::{
diff_named_ref_targets, diff_named_remote_refs, merge_ref_targets, merge_remote_refs, diff_named_ref_targets, diff_named_remote_refs, merge_ref_targets, merge_remote_refs,
}; };
use crate::revset::RevsetExpression; use crate::revset::{RevsetExpression, RevsetIteratorExt};
use crate::rewrite::{DescendantRebaser, RebaseOptions}; use crate::rewrite::{DescendantRebaser, RebaseOptions};
use crate::settings::{RepoSettings, UserSettings}; use crate::settings::{RepoSettings, UserSettings};
use crate::signing::{SignInitError, Signer}; use crate::signing::{SignInitError, Signer};
@ -772,7 +772,6 @@ pub struct MutableRepo {
base_repo: Arc<ReadonlyRepo>, base_repo: Arc<ReadonlyRepo>,
index: Box<dyn MutableIndex>, index: Box<dyn MutableIndex>,
view: DirtyCell<View>, view: DirtyCell<View>,
// TODO: make these fields private again
// The commit identified by the key has been replaced by all the ones in the value. // The commit identified by the key has been replaced by all the ones in the value.
// * Branches pointing to the old commit should be updated to the new commit, resulting in a // * Branches pointing to the old commit should be updated to the new commit, resulting in a
// conflict if there multiple new commits. // conflict if there multiple new commits.
@ -781,7 +780,7 @@ pub struct MutableRepo {
// * Working copies pointing to the old commit should be updated to the first of the new // * Working copies pointing to the old commit should be updated to the first of the new
// commits. However, if the type is `Abandoned`, a new working-copy commit should be created // commits. However, if the type is `Abandoned`, a new working-copy commit should be created
// on top of all of the new commits instead. // on top of all of the new commits instead.
pub(crate) parent_mapping: HashMap<CommitId, (RewriteType, Vec<CommitId>)>, parent_mapping: HashMap<CommitId, (RewriteType, Vec<CommitId>)>,
} }
impl MutableRepo { impl MutableRepo {
@ -1107,6 +1106,47 @@ impl MutableRepo {
self.set_view(view); self.set_view(view);
} }
/// Find descendants of commits in `parent_mapping` and then return them in
/// an order they should be rebased in. The result is in reverse order
/// so the next value can be removed from the end.
fn find_descendants_to_rebase(&self) -> Vec<Commit> {
let store = self.store();
let old_commits_expression =
RevsetExpression::commits(self.parent_mapping.keys().cloned().collect());
let to_visit_expression = old_commits_expression
.descendants()
.minus(&old_commits_expression);
let to_visit_revset = to_visit_expression.evaluate_programmatic(self).unwrap();
let to_visit: Vec<_> = to_visit_revset.iter().commits(store).try_collect().unwrap();
drop(to_visit_revset);
let to_visit_set: HashSet<CommitId> =
to_visit.iter().map(|commit| commit.id().clone()).collect();
let mut visited = HashSet::new();
// Calculate an order where we rebase parents first, but if the parents were
// rewritten, make sure we rebase the rewritten parent first.
dag_walk::topo_order_reverse(
to_visit,
|commit| commit.id().clone(),
|commit| {
visited.insert(commit.id().clone());
let mut dependents = vec![];
for parent in commit.parents() {
if let Some((_, targets)) = self.parent_mapping.get(parent.id()) {
for target in targets {
if to_visit_set.contains(target) && !visited.contains(target) {
dependents.push(store.get_commit(target).unwrap());
}
}
}
if to_visit_set.contains(parent.id()) {
dependents.push(parent);
}
}
dependents
},
)
}
/// After the rebaser returned by this function is dropped, /// After the rebaser returned by this function is dropped,
/// self.parent_mapping needs to be cleared. /// self.parent_mapping needs to be cleared.
fn rebase_descendants_return_rebaser<'settings, 'repo>( fn rebase_descendants_return_rebaser<'settings, 'repo>(
@ -1118,7 +1158,9 @@ impl MutableRepo {
// Optimization // Optimization
return Ok(None); return Ok(None);
} }
let mut rebaser = DescendantRebaser::new(settings, self);
let to_visit = self.find_descendants_to_rebase();
let mut rebaser = DescendantRebaser::new(settings, self, to_visit);
*rebaser.mut_options() = options; *rebaser.mut_options() = options;
rebaser.rebase_all()?; rebaser.rebase_all()?;
Ok(Some(rebaser)) Ok(Some(rebaser))

View file

@ -24,14 +24,12 @@ use tracing::instrument;
use crate::backend::{BackendError, BackendResult, CommitId, MergedTreeId}; use crate::backend::{BackendError, BackendResult, CommitId, MergedTreeId};
use crate::commit::Commit; use crate::commit::Commit;
use crate::dag_walk;
use crate::index::Index; use crate::index::Index;
use crate::matchers::{Matcher, Visit}; use crate::matchers::{Matcher, Visit};
use crate::merged_tree::{MergedTree, MergedTreeBuilder}; use crate::merged_tree::{MergedTree, MergedTreeBuilder};
use crate::object_id::ObjectId; use crate::object_id::ObjectId;
use crate::repo::{MutableRepo, Repo}; use crate::repo::{MutableRepo, Repo};
use crate::repo_path::RepoPath; use crate::repo_path::RepoPath;
use crate::revset::{RevsetExpression, RevsetIteratorExt};
use crate::settings::UserSettings; use crate::settings::UserSettings;
use crate::store::Store; use crate::store::Store;
@ -290,43 +288,8 @@ impl<'settings, 'repo> DescendantRebaser<'settings, 'repo> {
pub fn new( pub fn new(
settings: &'settings UserSettings, settings: &'settings UserSettings,
mut_repo: &'repo mut MutableRepo, mut_repo: &'repo mut MutableRepo,
to_visit: Vec<Commit>,
) -> DescendantRebaser<'settings, 'repo> { ) -> DescendantRebaser<'settings, 'repo> {
let store = mut_repo.store();
let old_commits_expression =
RevsetExpression::commits(mut_repo.parent_mapping.keys().cloned().collect());
let to_visit_expression = old_commits_expression
.descendants()
.minus(&old_commits_expression);
let to_visit_revset = to_visit_expression.evaluate_programmatic(mut_repo).unwrap();
let to_visit: Vec<_> = to_visit_revset.iter().commits(store).try_collect().unwrap();
drop(to_visit_revset);
let to_visit_set: HashSet<CommitId> =
to_visit.iter().map(|commit| commit.id().clone()).collect();
let mut visited = HashSet::new();
// Calculate an order where we rebase parents first, but if the parents were
// rewritten, make sure we rebase the rewritten parent first.
let to_visit = dag_walk::topo_order_reverse(
to_visit,
|commit| commit.id().clone(),
|commit| {
visited.insert(commit.id().clone());
let mut dependents = vec![];
for parent in commit.parents() {
if let Some((_, targets)) = mut_repo.parent_mapping.get(parent.id()) {
for target in targets {
if to_visit_set.contains(target) && !visited.contains(target) {
dependents.push(store.get_commit(target).unwrap());
}
}
}
if to_visit_set.contains(parent.id()) {
dependents.push(parent);
}
}
dependents
},
);
DescendantRebaser { DescendantRebaser {
settings, settings,
mut_repo, mut_repo,