diff --git a/lib/src/commit_builder.rs b/lib/src/commit_builder.rs index 9b1c1c174..c09d80e20 100644 --- a/lib/src/commit_builder.rs +++ b/lib/src/commit_builder.rs @@ -27,6 +27,7 @@ use crate::store::Store; pub struct CommitBuilder { store: Arc, commit: backend::Commit, + rewrite_source: Option, } pub fn new_change_id() -> ChangeId { @@ -63,6 +64,7 @@ impl CommitBuilder { CommitBuilder { store: store.clone(), commit, + rewrite_source: None, } } @@ -77,6 +79,7 @@ impl CommitBuilder { CommitBuilder { store: store.clone(), commit, + rewrite_source: Some(predecessor.clone()), } } @@ -101,6 +104,7 @@ impl CommitBuilder { CommitBuilder { store: store.clone(), commit, + rewrite_source: None, } } @@ -160,6 +164,16 @@ impl CommitBuilder { assert_eq!(parents.len(), 1); parents.clear(); } - repo.write_commit(self.commit) + let mut rewrite_source_id = None; + if let Some(rewrite_source) = self.rewrite_source { + if !self.commit.is_pruned && *rewrite_source.change_id() == self.commit.change_id { + rewrite_source_id.replace(rewrite_source.id().clone()); + } + } + let commit = repo.write_commit(self.commit); + if let Some(rewrite_source_id) = rewrite_source_id { + repo.record_rewritten_commit(rewrite_source_id, commit.id().clone()) + } + commit } } diff --git a/lib/tests/test_commit_builder.rs b/lib/tests/test_commit_builder.rs index 9e6f84637..cae4c3994 100644 --- a/lib/tests/test_commit_builder.rs +++ b/lib/tests/test_commit_builder.rs @@ -17,6 +17,7 @@ use jujutsu_lib::matchers::EverythingMatcher; use jujutsu_lib::repo_path::RepoPath; use jujutsu_lib::settings::UserSettings; use jujutsu_lib::testutils; +use jujutsu_lib::testutils::{assert_rebased, CommitGraphBuilder}; use jujutsu_lib::tree::DiffSummary; use test_case::test_case; @@ -146,3 +147,66 @@ fn test_rewrite(use_git: bool) { } ); } + +#[test_case(false ; "local backend")] +// #[test_case(true ; "git backend")] +fn test_commit_builder_descendants(use_git: bool) { + let settings = testutils::user_settings(); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); + let store = repo.store().clone(); + + let mut tx = repo.start_transaction("test"); + let mut graph_builder = CommitGraphBuilder::new(&settings, tx.mut_repo()); + let commit1 = graph_builder.initial_commit(); + let commit2 = graph_builder.commit_with_parents(&[&commit1]); + let commit3 = graph_builder.commit_with_parents(&[&commit2]); + let repo = tx.commit(); + + // Test with for_new_commit() + let mut tx = repo.start_transaction("test"); + CommitBuilder::for_new_commit(&settings, &store, store.empty_tree_id().clone()) + .write_to_repo(tx.mut_repo()); + let mut rebaser = tx.mut_repo().create_descendant_rebaser(&settings); + assert!(rebaser.rebase_next().is_none()); + tx.discard(); + + // Test with for_open_commit() + let mut tx = repo.start_transaction("test"); + CommitBuilder::for_open_commit( + &settings, + &store, + commit2.id().clone(), + store.empty_tree_id().clone(), + ) + .write_to_repo(tx.mut_repo()); + let mut rebaser = tx.mut_repo().create_descendant_rebaser(&settings); + assert!(rebaser.rebase_next().is_none()); + tx.discard(); + + // Test with for_rewrite_from() + let mut tx = repo.start_transaction("test"); + let commit4 = + CommitBuilder::for_rewrite_from(&settings, &store, &commit2).write_to_repo(tx.mut_repo()); + let mut rebaser = tx.mut_repo().create_descendant_rebaser(&settings); + assert_rebased(rebaser.rebase_next(), &commit3, &[&commit4]); + assert!(rebaser.rebase_next().is_none()); + tx.discard(); + + // Test with for_rewrite_from() but new change id + let mut tx = repo.start_transaction("test"); + CommitBuilder::for_rewrite_from(&settings, &store, &commit2) + .generate_new_change_id() + .write_to_repo(tx.mut_repo()); + let mut rebaser = tx.mut_repo().create_descendant_rebaser(&settings); + assert!(rebaser.rebase_next().is_none()); + tx.discard(); + + // Test with for_rewrite_from() but pruned + let mut tx = repo.start_transaction("test"); + CommitBuilder::for_rewrite_from(&settings, &store, &commit2) + .set_pruned(true) + .write_to_repo(tx.mut_repo()); + let mut rebaser = tx.mut_repo().create_descendant_rebaser(&settings); + assert!(rebaser.rebase_next().is_none()); + tx.discard(); +}