rewrite: flip inner/outer loops of mut_repo.new_parents()

This is basically a DFS to find leaf nodes. It will help omit duplicated
parent ids early.
This commit is contained in:
Yuya Nishihara 2024-08-28 19:21:38 +09:00
parent 8b6bebad40
commit d76d4a90a7

View file

@ -989,23 +989,20 @@ impl MutableRepo {
/// ///
/// Panics if `parent_mapping` contains cycles /// Panics if `parent_mapping` contains cycles
pub fn new_parents(&self, old_ids: Vec<CommitId>) -> Vec<CommitId> { pub fn new_parents(&self, old_ids: Vec<CommitId>) -> Vec<CommitId> {
fn single_substitution_round( let mut new_ids = Vec::with_capacity(old_ids.len());
parent_mapping: &HashMap<CommitId, Rewrite>, // The longest possible non-cycle substitution sequence goes through each key of
ids: Vec<CommitId>, // parent_mapping once.
) -> (Vec<CommitId>, bool) { let mut allowed_iterations = 0..self.parent_mapping.len();
let mut to_visit = old_ids.iter().rev().collect_vec();
while let Some(id) = to_visit.pop() {
let mut made_replacements = false; let mut made_replacements = false;
let mut new_ids = vec![]; match self.parent_mapping.get(id) {
// TODO(ilyagr): (Maybe?) optimize common case of replacements all
// being singletons. If CommitId-s were Copy. no allocations would be needed in
// that case, but it probably doesn't matter much while they are Vec<u8>-s.
for id in ids.into_iter() {
match parent_mapping.get(&id) {
None | Some(Rewrite::Divergent(_)) => { None | Some(Rewrite::Divergent(_)) => {
new_ids.push(id); new_ids.push(id.clone());
} }
Some(Rewrite::Rewritten(replacement)) => { Some(Rewrite::Rewritten(replacement)) => {
made_replacements = true; made_replacements = true;
new_ids.push(replacement.clone()) to_visit.push(replacement);
} }
Some(Rewrite::Abandoned(replacements)) => { Some(Rewrite::Abandoned(replacements)) => {
assert!( assert!(
@ -1017,22 +1014,12 @@ impl MutableRepo {
"Found empty value for key {id:?} in the parent mapping", "Found empty value for key {id:?} in the parent mapping",
); );
made_replacements = true; made_replacements = true;
new_ids.extend(replacements.iter().cloned()) to_visit.extend(replacements.iter().rev());
} }
};
} }
(new_ids, made_replacements)
}
let mut new_ids = old_ids;
// The longest possible non-cycle substitution sequence goes through each key of
// parent_mapping once.
let mut allowed_iterations = 0..self.parent_mapping.len();
loop {
let made_replacements;
(new_ids, made_replacements) = single_substitution_round(&self.parent_mapping, new_ids);
if !made_replacements { if !made_replacements {
break; allowed_iterations = 0..self.parent_mapping.len();
continue;
} }
allowed_iterations allowed_iterations
.next() .next()