tests: (mostly) stop using soon-to-be-private DescendantRebaser-related APIs

This removes uses of `DescendantRebaser::new` or
`MutRepo::create_descendant_rebaser` from most tests. The exceptions  are the
tests having to do with abandoning empty commits on rebase, since adjusting
those is a bit more elaborate (see follow-up commits).
This commit is contained in:
Ilya Grigoriev 2023-12-21 21:33:00 -08:00
parent 3eafca65ea
commit b2abba07e9
4 changed files with 278 additions and 244 deletions

View file

@ -19,7 +19,7 @@ use jj_lib::repo::Repo;
use jj_lib::repo_path::{RepoPath, RepoPathBuf}; use jj_lib::repo_path::{RepoPath, RepoPathBuf};
use jj_lib::settings::UserSettings; use jj_lib::settings::UserSettings;
use test_case::test_case; use test_case::test_case;
use testutils::{assert_rebased, create_tree, CommitGraphBuilder, TestRepo, TestRepoBackend}; use testutils::{assert_rebased_onto, create_tree, CommitGraphBuilder, TestRepo, TestRepoBackend};
fn to_owned_path_vec(paths: &[&RepoPath]) -> Vec<RepoPathBuf> { fn to_owned_path_vec(paths: &[&RepoPath]) -> Vec<RepoPathBuf> {
paths.iter().map(|&path| path.to_owned()).collect() paths.iter().map(|&path| path.to_owned()).collect()
@ -269,8 +269,11 @@ fn test_commit_builder_descendants(backend: TestRepoBackend) {
) )
.write() .write()
.unwrap(); .unwrap();
let mut rebaser = tx.mut_repo().create_descendant_rebaser(&settings); let rebase_map = tx
assert!(rebaser.rebase_next().unwrap().is_none()); .mut_repo()
.rebase_descendants_return_map(&settings)
.unwrap();
assert_eq!(rebase_map.len(), 0);
// Test with for_rewrite_from() // Test with for_rewrite_from()
let mut tx = repo.start_transaction(&settings); let mut tx = repo.start_transaction(&settings);
@ -279,9 +282,12 @@ fn test_commit_builder_descendants(backend: TestRepoBackend) {
.rewrite_commit(&settings, &commit2) .rewrite_commit(&settings, &commit2)
.write() .write()
.unwrap(); .unwrap();
let mut rebaser = tx.mut_repo().create_descendant_rebaser(&settings); let rebase_map = tx
assert_rebased(rebaser.rebase_next().unwrap(), &commit3, &[&commit4]); .mut_repo()
assert!(rebaser.rebase_next().unwrap().is_none()); .rebase_descendants_return_map(&settings)
.unwrap();
assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit3, &[commit4.id()]);
assert_eq!(rebase_map.len(), 1);
// Test with for_rewrite_from() but new change id // Test with for_rewrite_from() but new change id
let mut tx = repo.start_transaction(&settings); let mut tx = repo.start_transaction(&settings);
@ -290,6 +296,9 @@ fn test_commit_builder_descendants(backend: TestRepoBackend) {
.generate_new_change_id() .generate_new_change_id()
.write() .write()
.unwrap(); .unwrap();
let mut rebaser = tx.mut_repo().create_descendant_rebaser(&settings); let rebase_map = tx
assert!(rebaser.rebase_next().unwrap().is_none()); .mut_repo()
.rebase_descendants_return_map(&settings)
.unwrap();
assert!(rebase_map.is_empty());
} }

View file

@ -17,7 +17,7 @@ use jj_lib::op_store::{RefTarget, RemoteRef, RemoteRefState, WorkspaceId};
use jj_lib::repo::Repo; use jj_lib::repo::Repo;
use maplit::hashset; use maplit::hashset;
use testutils::{ use testutils::{
assert_rebased, create_random_commit, write_random_commit, CommitGraphBuilder, TestRepo, assert_rebased_onto, create_random_commit, write_random_commit, CommitGraphBuilder, TestRepo,
}; };
#[test] #[test]
@ -517,9 +517,7 @@ fn test_has_changed() {
#[test] #[test]
fn test_rebase_descendants_simple() { fn test_rebase_descendants_simple() {
// Tests that MutableRepo::create_descendant_rebaser() creates a // There are many additional tests of this functionality in `test_rewrite.rs`.
// DescendantRebaser that rebases descendants of rewritten and abandoned
// commits.
let settings = testutils::user_settings(); let settings = testutils::user_settings();
let test_repo = TestRepo::init(); let test_repo = TestRepo::init();
let repo = &test_repo.repo; let repo = &test_repo.repo;
@ -539,24 +537,29 @@ fn test_rebase_descendants_simple() {
let commit6 = graph_builder.commit_with_parents(&[&commit1]); let commit6 = graph_builder.commit_with_parents(&[&commit1]);
mut_repo.record_rewritten_commit(commit2.id().clone(), commit6.id().clone()); mut_repo.record_rewritten_commit(commit2.id().clone(), commit6.id().clone());
mut_repo.record_abandoned_commit(commit4.id().clone()); mut_repo.record_abandoned_commit(commit4.id().clone());
let mut rebaser = mut_repo.create_descendant_rebaser(&settings); let rebase_map = tx
.mut_repo()
.rebase_descendants_return_map(&settings)
.unwrap();
// Commit 3 got rebased onto commit 2's replacement, i.e. commit 6 // Commit 3 got rebased onto commit 2's replacement, i.e. commit 6
assert_rebased(rebaser.rebase_next().unwrap(), &commit3, &[&commit6]); assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit3, &[commit6.id()]);
// Commit 5 got rebased onto commit 4's parent, i.e. commit 1 // Commit 5 got rebased onto commit 4's parent, i.e. commit 1
assert_rebased(rebaser.rebase_next().unwrap(), &commit5, &[&commit1]); assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit5, &[commit1.id()]);
assert!(rebaser.rebase_next().unwrap().is_none()); assert_eq!(rebase_map.len(), 2);
// No more descendants to rebase if we try again. // No more descendants to rebase if we try again.
assert!(mut_repo let rebase_map = tx
.create_descendant_rebaser(&settings) .mut_repo()
.rebase_next() .rebase_descendants_return_map(&settings)
.unwrap() .unwrap();
.is_none()); assert_eq!(rebase_map.len(), 0);
} }
#[test] #[test]
fn test_rebase_descendants_conflicting_rewrite() { fn test_rebase_descendants_conflicting_rewrite() {
// Tests MutableRepo::create_descendant_rebaser() when a commit has been marked // Test rebasing descendants when one commit was rewritten to several other
// as rewritten to several other commits. // commits. There are many additional tests of this functionality in
// `test_rewrite.rs`.
let settings = testutils::user_settings(); let settings = testutils::user_settings();
let test_repo = TestRepo::init(); let test_repo = TestRepo::init();
let repo = &test_repo.repo; let repo = &test_repo.repo;
@ -575,16 +578,13 @@ fn test_rebase_descendants_conflicting_rewrite() {
let commit5 = graph_builder.commit_with_parents(&[&commit1]); let commit5 = graph_builder.commit_with_parents(&[&commit1]);
mut_repo.record_rewritten_commit(commit2.id().clone(), commit4.id().clone()); mut_repo.record_rewritten_commit(commit2.id().clone(), commit4.id().clone());
mut_repo.record_rewritten_commit(commit2.id().clone(), commit5.id().clone()); mut_repo.record_rewritten_commit(commit2.id().clone(), commit5.id().clone());
let mut rebaser = mut_repo.create_descendant_rebaser(&settings);
// Commit 3 does *not* get rebased because it's unclear if it should go onto // Commit 3 does *not* get rebased because it's unclear if it should go onto
// commit 4 or commit 5 // commit 4 or commit 5
assert!(rebaser.rebase_next().unwrap().is_none()); let rebase_map = tx
// No more descendants to rebase if we try again. .mut_repo()
assert!(mut_repo .rebase_descendants_return_map(&settings)
.create_descendant_rebaser(&settings) .unwrap();
.rebase_next() assert!(rebase_map.is_empty());
.unwrap()
.is_none());
} }
#[test] #[test]

View file

@ -25,8 +25,8 @@ use jj_lib::rewrite::{
use maplit::{hashmap, hashset}; use maplit::{hashmap, hashset};
use test_case::test_case; use test_case::test_case;
use testutils::{ use testutils::{
assert_rebased, create_random_commit, create_tree, write_random_commit, CommitGraphBuilder, assert_rebased, assert_rebased_onto, create_random_commit, create_tree, write_random_commit,
TestRepo, CommitGraphBuilder, TestRepo,
}; };
#[test] #[test]
@ -87,19 +87,17 @@ fn test_rebase_descendants_sideways() {
let commit_e = graph_builder.commit_with_parents(&[&commit_b]); let commit_e = graph_builder.commit_with_parents(&[&commit_b]);
let commit_f = graph_builder.commit_with_parents(&[&commit_a]); let commit_f = graph_builder.commit_with_parents(&[&commit_a]);
let mut rebaser = DescendantRebaser::new( tx.mut_repo()
&settings, .record_rewritten_commit(commit_b.id().clone(), commit_f.id().clone());
tx.mut_repo(), let rebase_map = tx
hashmap! { .mut_repo()
commit_b.id().clone() => hashset!{commit_f.id().clone()} .rebase_descendants_return_map(&settings)
}, .unwrap();
hashset! {}, assert_eq!(rebase_map.len(), 3);
); let new_commit_c = assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_c, &[commit_f.id()]);
let new_commit_c = assert_rebased(rebaser.rebase_next().unwrap(), &commit_c, &[&commit_f]); let new_commit_d =
let new_commit_d = assert_rebased(rebaser.rebase_next().unwrap(), &commit_d, &[&new_commit_c]); assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_d, &[new_commit_c.id()]);
let new_commit_e = assert_rebased(rebaser.rebase_next().unwrap(), &commit_e, &[&commit_f]); let new_commit_e = assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_e, &[commit_f.id()]);
assert!(rebaser.rebase_next().unwrap().is_none());
assert_eq!(rebaser.rebased().len(), 3);
assert_eq!( assert_eq!(
*tx.mut_repo().view().heads(), *tx.mut_repo().view().heads(),
@ -143,21 +141,23 @@ fn test_rebase_descendants_forward() {
let commit_f = graph_builder.commit_with_parents(&[&commit_d]); let commit_f = graph_builder.commit_with_parents(&[&commit_d]);
let commit_g = graph_builder.commit_with_parents(&[&commit_f]); let commit_g = graph_builder.commit_with_parents(&[&commit_f]);
let mut rebaser = DescendantRebaser::new( tx.mut_repo()
&settings, .record_rewritten_commit(commit_b.id().clone(), commit_f.id().clone());
tx.mut_repo(), let rebase_map = tx
hashmap! { .mut_repo()
commit_b.id().clone() => hashset!{commit_f.id().clone()} .rebase_descendants_return_map(&settings)
}, .unwrap();
hashset! {}, let new_commit_d =
); assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_d, &[&commit_f.id()]);
let new_commit_d = assert_rebased(rebaser.rebase_next().unwrap(), &commit_d, &[&commit_f]); let new_commit_f =
let new_commit_f = assert_rebased(rebaser.rebase_next().unwrap(), &commit_f, &[&new_commit_d]); assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_f, &[&new_commit_d.id()]);
let new_commit_c = assert_rebased(rebaser.rebase_next().unwrap(), &commit_c, &[&new_commit_f]); let new_commit_c =
let new_commit_e = assert_rebased(rebaser.rebase_next().unwrap(), &commit_e, &[&new_commit_d]); assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_c, &[&new_commit_f.id()]);
let new_commit_g = assert_rebased(rebaser.rebase_next().unwrap(), &commit_g, &[&new_commit_f]); let new_commit_e =
assert!(rebaser.rebase_next().unwrap().is_none()); assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_e, &[&new_commit_d.id()]);
assert_eq!(rebaser.rebased().len(), 5); let new_commit_g =
assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_g, &[&new_commit_f.id()]);
assert_eq!(rebase_map.len(), 5);
assert_eq!( assert_eq!(
*tx.mut_repo().view().heads(), *tx.mut_repo().view().heads(),
@ -198,19 +198,19 @@ fn test_rebase_descendants_reorder() {
let commit_h = graph_builder.commit_with_parents(&[&commit_f]); let commit_h = graph_builder.commit_with_parents(&[&commit_f]);
let commit_i = graph_builder.commit_with_parents(&[&commit_g]); let commit_i = graph_builder.commit_with_parents(&[&commit_g]);
let mut rebaser = DescendantRebaser::new( tx.mut_repo()
&settings, .record_rewritten_commit(commit_e.id().clone(), commit_d.id().clone());
tx.mut_repo(), tx.mut_repo()
hashmap! { .record_rewritten_commit(commit_c.id().clone(), commit_f.id().clone());
commit_e.id().clone() => hashset!{commit_d.id().clone()}, tx.mut_repo()
commit_c.id().clone() => hashset!{commit_f.id().clone()}, .record_rewritten_commit(commit_g.id().clone(), commit_h.id().clone());
commit_g.id().clone() => hashset!{commit_h.id().clone()}, let rebase_map = tx
}, .mut_repo()
hashset! {}, .rebase_descendants_return_map(&settings)
); .unwrap();
let new_commit_i = assert_rebased(rebaser.rebase_next().unwrap(), &commit_i, &[&commit_h]); let new_commit_i =
assert!(rebaser.rebase_next().unwrap().is_none()); assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_i, &[&commit_h.id()]);
assert_eq!(rebaser.rebased().len(), 1); assert_eq!(rebase_map.len(), 1);
assert_eq!( assert_eq!(
*tx.mut_repo().view().heads(), *tx.mut_repo().view().heads(),
@ -239,17 +239,15 @@ fn test_rebase_descendants_backward() {
let commit_c = graph_builder.commit_with_parents(&[&commit_b]); let commit_c = graph_builder.commit_with_parents(&[&commit_b]);
let commit_d = graph_builder.commit_with_parents(&[&commit_c]); let commit_d = graph_builder.commit_with_parents(&[&commit_c]);
let mut rebaser = DescendantRebaser::new( tx.mut_repo()
&settings, .record_rewritten_commit(commit_c.id().clone(), commit_b.id().clone());
tx.mut_repo(), let rebase_map = tx
hashmap! { .mut_repo()
commit_c.id().clone() => hashset!{commit_b.id().clone()} .rebase_descendants_return_map(&settings)
}, .unwrap();
hashset! {}, let new_commit_d =
); assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_d, &[&commit_b.id()]);
let new_commit_d = assert_rebased(rebaser.rebase_next().unwrap(), &commit_d, &[&commit_b]); assert_eq!(rebase_map.len(), 1);
assert!(rebaser.rebase_next().unwrap().is_none());
assert_eq!(rebaser.rebased().len(), 1);
assert_eq!( assert_eq!(
*tx.mut_repo().view().heads(), *tx.mut_repo().view().heads(),
@ -282,19 +280,19 @@ fn test_rebase_descendants_chain_becomes_branchy() {
let commit_e = graph_builder.commit_with_parents(&[&commit_a]); let commit_e = graph_builder.commit_with_parents(&[&commit_a]);
let commit_f = graph_builder.commit_with_parents(&[&commit_b]); let commit_f = graph_builder.commit_with_parents(&[&commit_b]);
let mut rebaser = DescendantRebaser::new( tx.mut_repo()
&settings, .record_rewritten_commit(commit_b.id().clone(), commit_e.id().clone());
tx.mut_repo(), tx.mut_repo()
hashmap! { .record_rewritten_commit(commit_c.id().clone(), commit_f.id().clone());
commit_b.id().clone() => hashset!{commit_e.id().clone()}, let rebase_map = tx
commit_c.id().clone() => hashset!{commit_f.id().clone()}, .mut_repo()
}, .rebase_descendants_return_map(&settings)
hashset! {}, .unwrap();
); let new_commit_f =
let new_commit_f = assert_rebased(rebaser.rebase_next().unwrap(), &commit_f, &[&commit_e]); assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_f, &[&commit_e.id()]);
let new_commit_d = assert_rebased(rebaser.rebase_next().unwrap(), &commit_d, &[&new_commit_f]); let new_commit_d =
assert!(rebaser.rebase_next().unwrap().is_none()); assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_d, &[&new_commit_f.id()]);
assert_eq!(rebaser.rebased().len(), 2); assert_eq!(rebase_map.len(), 2);
assert_eq!( assert_eq!(
*tx.mut_repo().view().heads(), *tx.mut_repo().view().heads(),
@ -329,23 +327,23 @@ fn test_rebase_descendants_internal_merge() {
let commit_e = graph_builder.commit_with_parents(&[&commit_c, &commit_d]); let commit_e = graph_builder.commit_with_parents(&[&commit_c, &commit_d]);
let commit_f = graph_builder.commit_with_parents(&[&commit_a]); let commit_f = graph_builder.commit_with_parents(&[&commit_a]);
let mut rebaser = DescendantRebaser::new( tx.mut_repo()
&settings, .record_rewritten_commit(commit_b.id().clone(), commit_f.id().clone());
let rebase_map = tx
.mut_repo()
.rebase_descendants_return_map(&settings)
.unwrap();
let new_commit_c =
assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_c, &[&commit_f.id()]);
let new_commit_d =
assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_d, &[&commit_f.id()]);
let new_commit_e = assert_rebased_onto(
tx.mut_repo(), tx.mut_repo(),
hashmap! { &rebase_map,
commit_b.id().clone() => hashset!{commit_f.id().clone()}
},
hashset! {},
);
let new_commit_c = assert_rebased(rebaser.rebase_next().unwrap(), &commit_c, &[&commit_f]);
let new_commit_d = assert_rebased(rebaser.rebase_next().unwrap(), &commit_d, &[&commit_f]);
let new_commit_e = assert_rebased(
rebaser.rebase_next().unwrap(),
&commit_e, &commit_e,
&[&new_commit_c, &new_commit_d], &[&new_commit_c.id(), &new_commit_d.id()],
); );
assert!(rebaser.rebase_next().unwrap().is_none()); assert_eq!(rebase_map.len(), 3);
assert_eq!(rebaser.rebased().len(), 3);
assert_eq!( assert_eq!(
*tx.mut_repo().view().heads(), *tx.mut_repo().view().heads(),
@ -379,21 +377,19 @@ fn test_rebase_descendants_external_merge() {
let commit_e = graph_builder.commit_with_parents(&[&commit_c, &commit_d]); let commit_e = graph_builder.commit_with_parents(&[&commit_c, &commit_d]);
let commit_f = graph_builder.commit_with_parents(&[&commit_a]); let commit_f = graph_builder.commit_with_parents(&[&commit_a]);
let mut rebaser = DescendantRebaser::new( tx.mut_repo()
&settings, .record_rewritten_commit(commit_c.id().clone(), commit_f.id().clone());
let rebase_map = tx
.mut_repo()
.rebase_descendants_return_map(&settings)
.unwrap();
let new_commit_e = assert_rebased_onto(
tx.mut_repo(), tx.mut_repo(),
hashmap! { &rebase_map,
commit_c.id().clone() => hashset!{commit_f.id().clone()}
},
hashset! {},
);
let new_commit_e = assert_rebased(
rebaser.rebase_next().unwrap(),
&commit_e, &commit_e,
&[&commit_f, &commit_d], &[&commit_f.id(), &commit_d.id()],
); );
assert!(rebaser.rebase_next().unwrap().is_none()); assert_eq!(rebase_map.len(), 1);
assert_eq!(rebaser.rebased().len(), 1);
assert_eq!( assert_eq!(
*tx.mut_repo().view().heads(), *tx.mut_repo().view().heads(),
@ -425,17 +421,19 @@ fn test_rebase_descendants_abandon() {
let commit_e = graph_builder.commit_with_parents(&[&commit_d]); let commit_e = graph_builder.commit_with_parents(&[&commit_d]);
let commit_f = graph_builder.commit_with_parents(&[&commit_e]); let commit_f = graph_builder.commit_with_parents(&[&commit_e]);
let mut rebaser = DescendantRebaser::new( tx.mut_repo().record_abandoned_commit(commit_b.id().clone());
&settings, tx.mut_repo().record_abandoned_commit(commit_e.id().clone());
tx.mut_repo(), let rebase_map = tx
hashmap! {}, .mut_repo()
hashset! {commit_b.id().clone(), commit_e.id().clone()}, .rebase_descendants_return_map(&settings)
); .unwrap();
let new_commit_c = assert_rebased(rebaser.rebase_next().unwrap(), &commit_c, &[&commit_a]); let new_commit_c =
let new_commit_d = assert_rebased(rebaser.rebase_next().unwrap(), &commit_d, &[&commit_a]); assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_c, &[&commit_a.id()]);
let new_commit_f = assert_rebased(rebaser.rebase_next().unwrap(), &commit_f, &[&new_commit_d]); let new_commit_d =
assert!(rebaser.rebase_next().unwrap().is_none()); assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_d, &[&commit_a.id()]);
assert_eq!(rebaser.rebased().len(), 3); let new_commit_f =
assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_f, &[&new_commit_d.id()]);
assert_eq!(rebase_map.len(), 3);
assert_eq!( assert_eq!(
*tx.mut_repo().view().heads(), *tx.mut_repo().view().heads(),
@ -463,14 +461,13 @@ fn test_rebase_descendants_abandon_no_descendants() {
let commit_b = graph_builder.commit_with_parents(&[&commit_a]); let commit_b = graph_builder.commit_with_parents(&[&commit_a]);
let commit_c = graph_builder.commit_with_parents(&[&commit_b]); let commit_c = graph_builder.commit_with_parents(&[&commit_b]);
let mut rebaser = DescendantRebaser::new( tx.mut_repo().record_abandoned_commit(commit_b.id().clone());
&settings, tx.mut_repo().record_abandoned_commit(commit_c.id().clone());
tx.mut_repo(), let rebase_map = tx
hashmap! {}, .mut_repo()
hashset! {commit_b.id().clone(), commit_c.id().clone()}, .rebase_descendants_return_map(&settings)
); .unwrap();
assert!(rebaser.rebase_next().unwrap().is_none()); assert_eq!(rebase_map.len(), 0);
assert_eq!(rebaser.rebased().len(), 0);
assert_eq!( assert_eq!(
*tx.mut_repo().view().heads(), *tx.mut_repo().view().heads(),
@ -502,15 +499,16 @@ fn test_rebase_descendants_abandon_and_replace() {
let commit_d = graph_builder.commit_with_parents(&[&commit_c]); let commit_d = graph_builder.commit_with_parents(&[&commit_c]);
let commit_e = graph_builder.commit_with_parents(&[&commit_a]); let commit_e = graph_builder.commit_with_parents(&[&commit_a]);
let mut rebaser = DescendantRebaser::new( tx.mut_repo()
&settings, .record_rewritten_commit(commit_b.id().clone(), commit_e.id().clone());
tx.mut_repo(), tx.mut_repo().record_abandoned_commit(commit_c.id().clone());
hashmap! {commit_b.id().clone() => hashset!{commit_e.id().clone()}}, let rebase_map = tx
hashset! {commit_c.id().clone()}, .mut_repo()
); .rebase_descendants_return_map(&settings)
let new_commit_d = assert_rebased(rebaser.rebase_next().unwrap(), &commit_d, &[&commit_e]); .unwrap();
assert!(rebaser.rebase_next().unwrap().is_none()); let new_commit_d =
assert_eq!(rebaser.rebased().len(), 1); assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_d, &[&commit_e.id()]);
assert_eq!(rebase_map.len(), 1);
assert_eq!( assert_eq!(
*tx.mut_repo().view().heads(), *tx.mut_repo().view().heads(),
@ -518,6 +516,7 @@ fn test_rebase_descendants_abandon_and_replace() {
); );
} }
// TODO(#2600): This behavior may need to change
#[test] #[test]
fn test_rebase_descendants_abandon_degenerate_merge() { fn test_rebase_descendants_abandon_degenerate_merge() {
let settings = testutils::user_settings(); let settings = testutils::user_settings();
@ -539,15 +538,14 @@ fn test_rebase_descendants_abandon_degenerate_merge() {
let commit_c = graph_builder.commit_with_parents(&[&commit_a]); let commit_c = graph_builder.commit_with_parents(&[&commit_a]);
let commit_d = graph_builder.commit_with_parents(&[&commit_b, &commit_c]); let commit_d = graph_builder.commit_with_parents(&[&commit_b, &commit_c]);
let mut rebaser = DescendantRebaser::new( tx.mut_repo().record_abandoned_commit(commit_b.id().clone());
&settings, let rebase_map = tx
tx.mut_repo(), .mut_repo()
hashmap! {}, .rebase_descendants_return_map(&settings)
hashset! {commit_b.id().clone()}, .unwrap();
); let new_commit_d =
let new_commit_d = assert_rebased(rebaser.rebase_next().unwrap(), &commit_d, &[&commit_c]); assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_d, &[&commit_c.id()]);
assert!(rebaser.rebase_next().unwrap().is_none()); assert_eq!(rebase_map.len(), 1);
assert_eq!(rebaser.rebased().len(), 1);
assert_eq!( assert_eq!(
*tx.mut_repo().view().heads(), *tx.mut_repo().view().heads(),
@ -580,19 +578,18 @@ fn test_rebase_descendants_abandon_widen_merge() {
let commit_e = graph_builder.commit_with_parents(&[&commit_b, &commit_c]); let commit_e = graph_builder.commit_with_parents(&[&commit_b, &commit_c]);
let commit_f = graph_builder.commit_with_parents(&[&commit_e, &commit_d]); let commit_f = graph_builder.commit_with_parents(&[&commit_e, &commit_d]);
let mut rebaser = DescendantRebaser::new( tx.mut_repo().record_abandoned_commit(commit_e.id().clone());
&settings, let rebase_map = tx
.mut_repo()
.rebase_descendants_return_map(&settings)
.unwrap();
let new_commit_f = assert_rebased_onto(
tx.mut_repo(), tx.mut_repo(),
hashmap! {}, &rebase_map,
hashset! {commit_e.id().clone()},
);
let new_commit_f = assert_rebased(
rebaser.rebase_next().unwrap(),
&commit_f, &commit_f,
&[&commit_b, &commit_c, &commit_d], &[&commit_b.id(), &commit_c.id(), &commit_d.id()],
); );
assert!(rebaser.rebase_next().unwrap().is_none()); assert_eq!(rebase_map.len(), 1);
assert_eq!(rebaser.rebased().len(), 1);
assert_eq!( assert_eq!(
*tx.mut_repo().view().heads(), *tx.mut_repo().view().heads(),
@ -623,19 +620,19 @@ fn test_rebase_descendants_multiple_sideways() {
let commit_e = graph_builder.commit_with_parents(&[&commit_d]); let commit_e = graph_builder.commit_with_parents(&[&commit_d]);
let commit_f = graph_builder.commit_with_parents(&[&commit_a]); let commit_f = graph_builder.commit_with_parents(&[&commit_a]);
let mut rebaser = DescendantRebaser::new( tx.mut_repo()
&settings, .record_rewritten_commit(commit_b.id().clone(), commit_f.id().clone());
tx.mut_repo(), tx.mut_repo()
hashmap! { .record_rewritten_commit(commit_d.id().clone(), commit_f.id().clone());
commit_b.id().clone() => hashset!{commit_f.id().clone()}, let rebase_map = tx
commit_d.id().clone() => hashset!{commit_f.id().clone()}, .mut_repo()
}, .rebase_descendants_return_map(&settings)
hashset! {}, .unwrap();
); let new_commit_c =
let new_commit_c = assert_rebased(rebaser.rebase_next().unwrap(), &commit_c, &[&commit_f]); assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_c, &[&commit_f.id()]);
let new_commit_e = assert_rebased(rebaser.rebase_next().unwrap(), &commit_e, &[&commit_f]); let new_commit_e =
assert!(rebaser.rebase_next().unwrap().is_none()); assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_e, &[&commit_f.id()]);
assert_eq!(rebaser.rebased().len(), 2); assert_eq!(rebase_map.len(), 2);
assert_eq!( assert_eq!(
*tx.mut_repo().view().heads(), *tx.mut_repo().view().heads(),
@ -668,18 +665,15 @@ fn test_rebase_descendants_multiple_swap() {
let commit_d = graph_builder.commit_with_parents(&[&commit_a]); let commit_d = graph_builder.commit_with_parents(&[&commit_a]);
let _commit_e = graph_builder.commit_with_parents(&[&commit_d]); let _commit_e = graph_builder.commit_with_parents(&[&commit_d]);
let mut rebaser = DescendantRebaser::new( tx.mut_repo()
&settings, .record_rewritten_commit(commit_b.id().clone(), commit_d.id().clone());
tx.mut_repo(), tx.mut_repo()
hashmap! { .record_rewritten_commit(commit_d.id().clone(), commit_b.id().clone());
commit_b.id().clone() => hashset!{commit_d.id().clone()}, let _ = tx.mut_repo().rebase_descendants_return_map(&settings); // Panics because of the cycle
commit_d.id().clone() => hashset!{commit_b.id().clone()},
},
hashset! {},
);
let _ = rebaser.rebase_next(); // Panics because of the cycle
} }
// Unlike `test_rebase_descendants_multiple_swap`, this does not currently
// panic, but it would probably be OK if it did.
#[test] #[test]
fn test_rebase_descendants_multiple_no_descendants() { fn test_rebase_descendants_multiple_no_descendants() {
let settings = testutils::user_settings(); let settings = testutils::user_settings();
@ -697,17 +691,15 @@ fn test_rebase_descendants_multiple_no_descendants() {
let commit_b = graph_builder.commit_with_parents(&[&commit_a]); let commit_b = graph_builder.commit_with_parents(&[&commit_a]);
let commit_c = graph_builder.commit_with_parents(&[&commit_a]); let commit_c = graph_builder.commit_with_parents(&[&commit_a]);
let mut rebaser = DescendantRebaser::new( tx.mut_repo()
&settings, .record_rewritten_commit(commit_b.id().clone(), commit_c.id().clone());
tx.mut_repo(), tx.mut_repo()
hashmap! { .record_rewritten_commit(commit_c.id().clone(), commit_b.id().clone());
commit_b.id().clone() => hashset!{commit_c.id().clone()}, let rebase_map = tx
commit_c.id().clone() => hashset!{commit_b.id().clone()}, .mut_repo()
}, .rebase_descendants_return_map(&settings)
hashset! {}, .unwrap();
); assert!(rebase_map.is_empty());
assert!(rebaser.rebase_next().unwrap().is_none());
assert!(rebaser.rebased().is_empty());
assert_eq!( assert_eq!(
*tx.mut_repo().view().heads(), *tx.mut_repo().view().heads(),
@ -758,20 +750,24 @@ fn test_rebase_descendants_divergent_rewrite() {
let commit_d3 = graph_builder.commit_with_parents(&[&commit_a]); let commit_d3 = graph_builder.commit_with_parents(&[&commit_a]);
let commit_f2 = graph_builder.commit_with_parents(&[&commit_a]); let commit_f2 = graph_builder.commit_with_parents(&[&commit_a]);
let mut rebaser = DescendantRebaser::new( tx.mut_repo()
&settings, .record_rewritten_commit(commit_b.id().clone(), commit_b2.id().clone());
tx.mut_repo(), // Commit D becomes divergent
hashmap! { tx.mut_repo()
commit_b.id().clone() => hashset!{commit_b2.id().clone()}, .record_rewritten_commit(commit_d.id().clone(), commit_d2.id().clone());
commit_d.id().clone() => hashset!{commit_d2.id().clone(), commit_d3.id().clone()}, tx.mut_repo()
commit_f.id().clone() => hashset!{commit_f2.id().clone()}, .record_rewritten_commit(commit_d.id().clone(), commit_d3.id().clone());
}, tx.mut_repo()
hashset! {}, .record_rewritten_commit(commit_f.id().clone(), commit_f2.id().clone());
); let rebase_map = tx
let new_commit_c = assert_rebased(rebaser.rebase_next().unwrap(), &commit_c, &[&commit_b2]); .mut_repo()
let new_commit_g = assert_rebased(rebaser.rebase_next().unwrap(), &commit_g, &[&commit_f2]); .rebase_descendants_return_map(&settings)
assert!(rebaser.rebase_next().unwrap().is_none()); .unwrap();
assert_eq!(rebaser.rebased().len(), 2); let new_commit_c =
assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_c, &[commit_b2.id()]);
let new_commit_g =
assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_g, &[&commit_f2.id()]);
assert_eq!(rebase_map.len(), 2); // Commit E is not rebased
assert_eq!( assert_eq!(
*tx.mut_repo().view().heads(), *tx.mut_repo().view().heads(),
@ -814,10 +810,12 @@ fn test_rebase_descendants_repeated() {
.set_description("b2") .set_description("b2")
.write() .write()
.unwrap(); .unwrap();
let mut rebaser = tx.mut_repo().create_descendant_rebaser(&settings); let rebase_map = tx
let commit_c2 = assert_rebased(rebaser.rebase_next().unwrap(), &commit_c, &[&commit_b2]); .mut_repo()
assert!(rebaser.rebase_next().unwrap().is_none()); .rebase_descendants_return_map(&settings)
assert_eq!(rebaser.rebased().len(), 1); .unwrap();
let commit_c2 = assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_c, &[commit_b2.id()]);
assert_eq!(rebase_map.len(), 1);
assert_eq!( assert_eq!(
*tx.mut_repo().view().heads(), *tx.mut_repo().view().heads(),
@ -827,9 +825,11 @@ fn test_rebase_descendants_repeated() {
); );
// We made no more changes, so nothing should be rebased. // We made no more changes, so nothing should be rebased.
let mut rebaser = tx.mut_repo().create_descendant_rebaser(&settings); let rebase_map = tx
assert!(rebaser.rebase_next().unwrap().is_none()); .mut_repo()
assert_eq!(rebaser.rebased().len(), 0); .rebase_descendants_return_map(&settings)
.unwrap();
assert_eq!(rebase_map.len(), 0);
// Now mark B3 as rewritten from B2 and rebase descendants again. // Now mark B3 as rewritten from B2 and rebase descendants again.
let commit_b3 = tx let commit_b3 = tx
@ -838,10 +838,12 @@ fn test_rebase_descendants_repeated() {
.set_description("b3") .set_description("b3")
.write() .write()
.unwrap(); .unwrap();
let mut rebaser = tx.mut_repo().create_descendant_rebaser(&settings); let rebase_map = tx
let commit_c3 = assert_rebased(rebaser.rebase_next().unwrap(), &commit_c2, &[&commit_b3]); .mut_repo()
assert!(rebaser.rebase_next().unwrap().is_none()); .rebase_descendants_return_map(&settings)
assert_eq!(rebaser.rebased().len(), 1); .unwrap();
let commit_c3 = assert_rebased_onto(tx.mut_repo(), &rebase_map, &commit_c2, &[commit_b3.id()]);
assert_eq!(rebase_map.len(), 1);
assert_eq!( assert_eq!(
*tx.mut_repo().view().heads(), *tx.mut_repo().view().heads(),
@ -900,20 +902,16 @@ fn test_rebase_descendants_contents() {
.write() .write()
.unwrap(); .unwrap();
let mut rebaser = DescendantRebaser::new( tx.mut_repo()
&settings, .record_rewritten_commit(commit_b.id().clone(), commit_d.id().clone());
tx.mut_repo(), let rebase_map = tx
hashmap! { .mut_repo()
commit_b.id().clone() => hashset!{commit_d.id().clone()} .rebase_descendants_return_map(&settings)
}, .unwrap();
hashset! {}, assert_eq!(rebase_map.len(), 1);
);
rebaser.rebase_all().unwrap();
let rebased = rebaser.rebased();
assert_eq!(rebased.len(), 1);
let new_commit_c = repo let new_commit_c = repo
.store() .store()
.get_commit(rebased.get(commit_c.id()).unwrap()) .get_commit(rebase_map.get(commit_c.id()).unwrap())
.unwrap(); .unwrap();
let tree_b = commit_b.tree().unwrap(); let tree_b = commit_b.tree().unwrap();

View file

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use std::collections::HashMap;
use std::env; use std::env;
use std::fs::{self, OpenOptions}; use std::fs::{self, OpenOptions};
use std::io::{Read, Write}; use std::io::{Read, Write};
@ -20,8 +21,8 @@ use std::sync::{Arc, Once};
use itertools::Itertools; use itertools::Itertools;
use jj_lib::backend::{ use jj_lib::backend::{
self, Backend, BackendInitError, ChangeId, FileId, MergedTreeId, MillisSinceEpoch, ObjectId, self, Backend, BackendInitError, ChangeId, CommitId, FileId, MergedTreeId, MillisSinceEpoch,
Signature, Timestamp, TreeValue, ObjectId, Signature, Timestamp, TreeValue,
}; };
use jj_lib::commit::Commit; use jj_lib::commit::Commit;
use jj_lib::commit_builder::CommitBuilder; use jj_lib::commit_builder::CommitBuilder;
@ -452,6 +453,32 @@ impl<'settings, 'repo> CommitGraphBuilder<'settings, 'repo> {
} }
} }
pub fn assert_rebased_onto(
repo: &impl Repo,
rebased: &HashMap<CommitId, CommitId>,
expected_old_commit: &Commit,
expected_new_parent_ids: &[&CommitId],
) -> Commit {
let new_commit_id = rebased.get(expected_old_commit.id()).unwrap_or_else(|| {
panic!(
"Expected commit to have been rebased: {}",
expected_old_commit.id().hex()
)
});
let new_commit = repo.store().get_commit(new_commit_id).unwrap().clone();
assert_eq!(new_commit.change_id(), expected_old_commit.change_id());
assert_eq!(
new_commit.parent_ids().to_vec(),
expected_new_parent_ids
.iter()
.map(|x| (*x).clone())
.collect_vec()
);
new_commit
}
// Short-term TODO: We will delete this function shortly; it will be replaced by
// `assert_rebased_onto` above
pub fn assert_rebased( pub fn assert_rebased(
rebased: Option<RebasedDescendant>, rebased: Option<RebasedDescendant>,
expected_old_commit: &Commit, expected_old_commit: &Commit,