Skip to content

Commit

Permalink
git: add tests that simulate external checkout/amend in colocated repo
Browse files Browse the repository at this point in the history
I'm going to change the behavior of _without_ref() case to mitigate #1042.
  • Loading branch information
yuja committed May 11, 2023
1 parent aa54fba commit 66d405f
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 0 deletions.
103 changes: 103 additions & 0 deletions lib/tests/test_git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,109 @@ fn test_import_refs_reimport_git_head_counts() {
assert!(tx.mut_repo().view().heads().contains(&jj_id(&commit)));
}

#[test]
fn test_import_refs_reimport_git_head_without_ref() {
// Simulate external `git checkout` in colocated repo, from anonymous branch.
let settings = testutils::user_settings();
let git_settings = GitSettings::default();
let test_repo = TestRepo::init(true);
let repo = &test_repo.repo;
let git_repo = repo.store().git_repo().unwrap();

// First, HEAD points to commit1.
let mut tx = repo.start_transaction(&settings, "test");
let commit1 = write_random_commit(tx.mut_repo(), &settings);
let commit2 = write_random_commit(tx.mut_repo(), &settings);
git_repo.set_head_detached(git_id(&commit1)).unwrap();

// Import HEAD.
git::import_refs(tx.mut_repo(), &git_repo, &git_settings).unwrap();
tx.mut_repo().rebase_descendants(&settings).unwrap();
assert!(tx.mut_repo().view().heads().contains(commit1.id()));
assert!(tx.mut_repo().view().heads().contains(commit2.id()));

// Move HEAD to commit2 (by e.g. `git checkout` command)
git_repo.set_head_detached(git_id(&commit2)).unwrap();

// Reimport HEAD, which abandons the old HEAD branch because jj thinks it
// would be rewritten by e.g. `git commit --amend` command.
git::import_refs(tx.mut_repo(), &git_repo, &git_settings).unwrap();
tx.mut_repo().rebase_descendants(&settings).unwrap();
assert!(!tx.mut_repo().view().heads().contains(commit1.id()));
assert!(tx.mut_repo().view().heads().contains(commit2.id()));
}

#[test]
fn test_import_refs_reimport_git_head_with_moved_ref() {
// Simulate external history rewriting in colocated repo.
let settings = testutils::user_settings();
let git_settings = GitSettings::default();
let test_repo = TestRepo::init(true);
let repo = &test_repo.repo;
let git_repo = repo.store().git_repo().unwrap();

// First, both HEAD and main point to commit1.
let mut tx = repo.start_transaction(&settings, "test");
let commit1 = write_random_commit(tx.mut_repo(), &settings);
let commit2 = write_random_commit(tx.mut_repo(), &settings);
git_repo
.reference("refs/heads/main", git_id(&commit1), true, "test")
.unwrap();
git_repo.set_head_detached(git_id(&commit1)).unwrap();

// Import HEAD and main.
git::import_refs(tx.mut_repo(), &git_repo, &git_settings).unwrap();
tx.mut_repo().rebase_descendants(&settings).unwrap();
assert!(tx.mut_repo().view().heads().contains(commit1.id()));
assert!(tx.mut_repo().view().heads().contains(commit2.id()));

// Move both HEAD and main to commit2 (by e.g. `git commit --amend` command)
git_repo
.reference("refs/heads/main", git_id(&commit2), true, "test")
.unwrap();
git_repo.set_head_detached(git_id(&commit2)).unwrap();

// Reimport HEAD and main, which abandons the old HEAD/main branch.
git::import_refs(tx.mut_repo(), &git_repo, &git_settings).unwrap();
tx.mut_repo().rebase_descendants(&settings).unwrap();
assert!(!tx.mut_repo().view().heads().contains(commit1.id()));
assert!(tx.mut_repo().view().heads().contains(commit2.id()));
}

#[test]
fn test_import_refs_reimport_git_head_with_fixed_ref() {
// Simulate external `git checkout` in colocated repo, from named branch.
let settings = testutils::user_settings();
let git_settings = GitSettings::default();
let test_repo = TestRepo::init(true);
let repo = &test_repo.repo;
let git_repo = repo.store().git_repo().unwrap();

// First, both HEAD and main point to commit1.
let mut tx = repo.start_transaction(&settings, "test");
let commit1 = write_random_commit(tx.mut_repo(), &settings);
let commit2 = write_random_commit(tx.mut_repo(), &settings);
git_repo
.reference("refs/heads/main", git_id(&commit1), true, "test")
.unwrap();
git_repo.set_head_detached(git_id(&commit1)).unwrap();

// Import HEAD and main.
git::import_refs(tx.mut_repo(), &git_repo, &git_settings).unwrap();
tx.mut_repo().rebase_descendants(&settings).unwrap();
assert!(tx.mut_repo().view().heads().contains(commit1.id()));
assert!(tx.mut_repo().view().heads().contains(commit2.id()));

// Move only HEAD to commit2 (by e.g. `git checkout` command)
git_repo.set_head_detached(git_id(&commit2)).unwrap();

// Reimport HEAD, which shouldn't abandon the old HEAD branch.
git::import_refs(tx.mut_repo(), &git_repo, &git_settings).unwrap();
tx.mut_repo().rebase_descendants(&settings).unwrap();
assert!(tx.mut_repo().view().heads().contains(commit1.id()));
assert!(tx.mut_repo().view().heads().contains(commit2.id()));
}

#[test]
fn test_import_refs_reimport_all_from_root_removed() {
// Test that if a chain of commits all the way from the root gets unreferenced,
Expand Down
38 changes: 38 additions & 0 deletions tests/test_git_colocated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,44 @@ fn test_git_colocated_fetch_deleted_branch() {
"###);
}

#[test]
fn test_git_colocated_external_checkout() {
let test_env = TestEnvironment::default();
let repo_path = test_env.env_root().join("repo");
let git_repo = git2::Repository::init(&repo_path).unwrap();
test_env.jj_cmd_success(&repo_path, &["init", "--git-repo=."]);
test_env.jj_cmd_success(&repo_path, &["ci", "-m=A"]);
test_env.jj_cmd_success(&repo_path, &["new", "-m=B", "root"]);
test_env.jj_cmd_success(&repo_path, &["new"]);

// Checked out anonymous branch
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
@ 53637cd508ff02427dd78eca98f5b2450a6370ce
◉ 66f4d1806ae41bd604f69155dece64062a0056cf
│ ◉ a86754f975f953fa25da4265764adc0c62e9ce6b master
├─╯
◉ 0000000000000000000000000000000000000000
"###);

// Check out another branch by external command
git_repo
.set_head_detached(
git_repo
.find_reference("refs/heads/master")
.unwrap()
.target()
.unwrap(),
)
.unwrap();

// The old HEAD branch gets abandoned because jj thinks it has been rewritten.
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###"
@ 0521ce3b8c4e29aab79f3c750e2845dcbc4c3874
◉ a86754f975f953fa25da4265764adc0c62e9ce6b master
◉ 0000000000000000000000000000000000000000
"###);
}

#[test]
fn test_git_colocated_squash_undo() {
let test_env = TestEnvironment::default();
Expand Down

0 comments on commit 66d405f

Please sign in to comment.