forked from mirrors/jj
evolution: don't create merge commits with one parent ancestor of another
This commit is contained in:
parent
443528159e
commit
1a4d9d5644
2 changed files with 42 additions and 6 deletions
|
@ -572,7 +572,7 @@ impl<'settings> OrphanResolver<'settings> {
|
|||
self.remaining_orphans.pop().map(|orphan_pos| {
|
||||
let store = mut_repo.store();
|
||||
let orphan_entry = mut_repo.index().entry_by_pos(orphan_pos);
|
||||
let mut new_parents = vec![];
|
||||
let mut new_parent_ids = vec![];
|
||||
let mut ambiguous_new_parents = false;
|
||||
let evolution = mut_repo.evolution();
|
||||
for old_parent in orphan_entry.parents() {
|
||||
|
@ -582,16 +582,17 @@ impl<'settings> OrphanResolver<'settings> {
|
|||
ambiguous_new_parents = true;
|
||||
break;
|
||||
}
|
||||
new_parents.push(
|
||||
store
|
||||
.get_commit(new_parent_candidates.iter().next().unwrap())
|
||||
.unwrap(),
|
||||
);
|
||||
new_parent_ids.push(new_parent_candidates.into_iter().next().unwrap());
|
||||
}
|
||||
let orphan = store.get_commit(&orphan_entry.commit_id()).unwrap();
|
||||
if ambiguous_new_parents {
|
||||
OrphanResolution::AmbiguousTarget { orphan }
|
||||
} else {
|
||||
let mut new_parents = vec![];
|
||||
// Don't create commit where one parent is an ancestor of another.
|
||||
for new_parent_id in mut_repo.index().heads(&new_parent_ids) {
|
||||
new_parents.push(store.get_commit(&new_parent_id).unwrap());
|
||||
}
|
||||
let new_commit = rebase_commit(self.user_settings, mut_repo, &orphan, &new_parents);
|
||||
OrphanResolution::Resolved { orphan, new_commit }
|
||||
}
|
||||
|
|
|
@ -552,6 +552,41 @@ fn test_evolve_orphan(use_git: bool) {
|
|||
tx.discard();
|
||||
}
|
||||
|
||||
#[test_case(false ; "local store")]
|
||||
// #[test_case(true ; "git store")]
|
||||
/// When evolving a merge commit, the new commit should not have a parent that
|
||||
/// is an ancestor of another parent.
|
||||
fn test_evolve_orphan_merge_ancestor_of_other_parent(use_git: bool) {
|
||||
let settings = testutils::user_settings();
|
||||
let (_temp_dir, repo) = testutils::init_repo(&settings, use_git);
|
||||
let root_commit = repo.store().root_commit();
|
||||
|
||||
let mut tx = repo.start_transaction("test");
|
||||
let mut_repo = tx.mut_repo();
|
||||
let initial = child_commit(&settings, &repo, &root_commit).write_to_repo(mut_repo);
|
||||
let child1 = child_commit(&settings, &repo, &initial).write_to_repo(mut_repo);
|
||||
let child2 = child_commit(&settings, &repo, &initial).write_to_repo(mut_repo);
|
||||
let merge = testutils::create_random_commit(&settings, &repo)
|
||||
.set_parents(vec![child1.id().clone(), child2.id().clone()])
|
||||
.write_to_repo(mut_repo);
|
||||
|
||||
let rewritten_child2 = CommitBuilder::for_rewrite_from(&settings, repo.store(), &child2)
|
||||
.set_parents(vec![child1.id().clone()])
|
||||
.set_description("rewritten child2".to_string())
|
||||
.write_to_repo(mut_repo);
|
||||
|
||||
let mut resolver = OrphanResolver::new(&settings, mut_repo);
|
||||
let resolution = resolver.resolve_next(mut_repo);
|
||||
assert_matches!(resolution, Some(OrphanResolution::Resolved { .. }));
|
||||
assert_eq!(resolver.resolve_next(mut_repo), None);
|
||||
if let Some(OrphanResolution::Resolved { orphan, new_commit }) = resolution {
|
||||
assert_eq!(orphan, merge);
|
||||
assert_eq!(new_commit.parents(), vec![rewritten_child2]);
|
||||
}
|
||||
|
||||
tx.discard();
|
||||
}
|
||||
|
||||
#[test_case(false ; "local store")]
|
||||
#[test_case(true ; "git store")]
|
||||
fn test_evolve_pruned_orphan(use_git: bool) {
|
||||
|
|
Loading…
Reference in a new issue