jj/cli/tests/test_identical_commits.rs
Martin von Zweigbergk 15b0225547 tests: test attempt to create identical commits
We currently don't allow you to create two identical commits. It
results in an internal error. I think we need to allow it. Let's start
by testing the current behavior.

I created these as CLI tests because I want to make sure that `evolog`
and `op diff` get tested, including rendering.
2025-10-27 16:35:47 +00:00

223 lines
8 KiB
Rust

// Copyright 2025 The Jujutsu Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::common::CommandOutput;
use crate::common::TestEnvironment;
use crate::common::TestWorkDir;
fn create_test_environment() -> TestEnvironment {
let mut test_env = TestEnvironment::default();
test_env.add_env_var("JJ_RANDOMNESS_SEED", "0");
test_env.add_env_var("JJ_TIMESTAMP", "2001-01-01T00:00:00+00:00");
test_env.add_config("experimental.record-predecessors-in-commit = false");
test_env
}
#[test]
fn test_identical_commits() {
let test_env = create_test_environment();
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
let work_dir = test_env.work_dir("repo");
work_dir.run_jj(["new", "root()", "-m=test"]).success();
// TODO: Should not fail
insta::assert_snapshot!(work_dir.run_jj(["new", "root()", "-m=test"]), @r"
------- stderr -------
Internal error: Unexpected error from backend
Caused by: Newly-created commit e94ed463cbb0776612e308eba2ecaae74a7f8a73 already exists
[EOF]
[exit status: 255]
");
// There should be a single "test" commit
insta::assert_snapshot!(get_log_output(&work_dir), @r"
@ e94ed463cbb0 test
◆ 000000000000
[EOF]
");
}
/// Create "test1" commit, then rewrite it in the same way "concurrently" (by
/// starting at the same operation)
#[test]
fn test_identical_commits_concurrently() {
let test_env = create_test_environment();
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
let work_dir = test_env.work_dir("repo");
work_dir.run_jj(["new", "root()", "-m=test1"]).success();
work_dir.run_jj(["describe", "-m=test2"]).success();
work_dir
.run_jj(["describe", "-m=test2", "--at-op=@-"])
.success();
// There should be a single "test2" commit
insta::assert_snapshot!(get_log_output(&work_dir), @r"
@ c5abd2256ac0 test2
◆ 000000000000
[EOF]
------- stderr -------
Concurrent modification detected, resolving automatically.
[EOF]
");
}
/// Create commit "test1", then rewrite it to "test2", then rewrite it back to
/// "test1"
#[test]
fn test_identical_commits_by_cycling_rewrite() {
let test_env = create_test_environment();
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
let work_dir = test_env.work_dir("repo");
work_dir.run_jj(["new", "root()", "-m=test1"]).success();
work_dir.run_jj(["describe", "-m=test2"]).success();
// TODO: Should not fail
insta::assert_snapshot!(work_dir.run_jj(["describe", "-m=test1"]), @r"
------- stderr -------
Internal error: Unexpected error from backend
Caused by: Newly-created commit 053222c21fa06b9492e22346f8f70e732231ad4f already exists
[EOF]
[exit status: 255]
");
insta::assert_snapshot!(work_dir.run_jj(["evolog"]), @r"
@ oxmtprsl test.user@example.com 2001-01-01 11:00:00 c5abd225
│ (empty) test2
│ -- operation f184243937e9 describe commit 053222c21fa06b9492e22346f8f70e732231ad4f
○ oxmtprsl hidden test.user@example.com 2001-01-01 11:00:00 053222c2
(empty) test1
-- operation 509c18587028 new empty commit
[EOF]
");
// TODO: Test `jj op diff --from @--`
}
/// Create commits "test1" and "test2" and rewrite "test1". Then rewrite "test2"
/// to become identical to the rewritten "test1".
#[test]
fn test_identical_commits_by_convergent_rewrite() {
let test_env = create_test_environment();
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
let work_dir = test_env.work_dir("repo");
work_dir.run_jj(["new", "root()", "-m=test1"]).success();
work_dir.run_jj(["new", "root()", "-m=test2"]).success();
work_dir
.run_jj(["describe", "-m=test3", "description(test1)"])
.success();
// TODO: Should not fail
insta::assert_snapshot!(work_dir.run_jj(["describe", "-m=test3", "description(test2)"]), @r"
------- stderr -------
Internal error: Unexpected error from backend
Caused by: Newly-created commit 460733f1f6f9283d5a810b231dd3f846fd3a6f04 already exists
[EOF]
[exit status: 255]
");
// TODO: The "test3" commit should have either "test1" or "test2" as predecessor
// (or both?)
insta::assert_snapshot!(work_dir.run_jj(["evolog"]), @r"
@ oxmtprsl?? test.user@example.com 2001-01-01 11:00:00 c5abd225
(empty) test2
-- operation a1561db9359b new empty commit
[EOF]
");
}
/// Create commits "test1" and "test2" and then rewrite both of them to be
/// identical in a single operation
#[test]
fn test_identical_commits_by_convergent_rewrite_one_operation() {
let test_env = create_test_environment();
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
let work_dir = test_env.work_dir("repo");
work_dir.run_jj(["new", "root()", "-m=test1"]).success();
work_dir.run_jj(["new", "root()", "-m=test2"]).success();
// TODO: Should not fail
insta::assert_snapshot!(work_dir.run_jj(["describe", "-m=test3", "root()+"]), @r"
------- stderr -------
Internal error: Unexpected error from backend
Caused by: Newly-created commit 460733f1f6f9283d5a810b231dd3f846fd3a6f04 already exists
[EOF]
[exit status: 255]
");
// TODO: There should be a single "test3" commit
insta::assert_snapshot!(get_log_output(&work_dir), @r"
@ c5abd2256ac0 test2
│ ○ 053222c21fa0 test1
├─╯
◆ 000000000000
[EOF]
");
// TODO: The "test3" commit should have either "test1" or "test2" as predecessor
// (or both?)
insta::assert_snapshot!(work_dir.run_jj(["evolog"]), @r"
@ oxmtprsl?? test.user@example.com 2001-01-01 11:00:00 c5abd225
(empty) test2
-- operation a1561db9359b new empty commit
[EOF]
");
}
/// Create two stacked commits. Then reorder them so they become rewrites of
/// each other.
#[test]
fn test_identical_commits_swap_by_reordering() {
let test_env = create_test_environment();
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
let work_dir = test_env.work_dir("repo");
work_dir.run_jj(["new", "root()", "-m=test"]).success();
work_dir.run_jj(["new", "-m=test"]).success();
// Test the setup
insta::assert_snapshot!(get_log_output(&work_dir), @r"
@ 5bae90c9b34d test
○ e94ed463cbb0 test
◆ 000000000000
[EOF]
");
// TODO: Should not fail
insta::assert_snapshot!(work_dir.run_jj(["rebase", "-r=@", "-B=@-"]), @r"
------- stderr -------
Internal error: Unexpected error from backend
Caused by: Newly-created commit e94ed463cbb0776612e308eba2ecaae74a7f8a73 already exists
[EOF]
[exit status: 255]
");
// There same two commits should still be visible
insta::assert_snapshot!(get_log_output(&work_dir), @r"
@ 5bae90c9b34d test
○ e94ed463cbb0 test
◆ 000000000000
[EOF]
");
// TODO: Each commit should be a predecessor of the other
insta::assert_snapshot!(work_dir.run_jj(["evolog", "-r=@"]), @r"
@ oxmtprsl?? test.user@example.com 2001-01-01 11:00:00 5bae90c9
(empty) test
-- operation 380fbe20623e new empty commit
[EOF]
");
insta::assert_snapshot!(work_dir.run_jj(["evolog", "-r=@-"]), @r"
○ oxmtprsl?? test.user@example.com 2001-01-01 11:00:00 e94ed463
(empty) test
-- operation 40e37b931010 new empty commit
[EOF]
");
// TODO: Test that `jj op show` displays something reasonable
}
#[must_use]
fn get_log_output(work_dir: &TestWorkDir) -> CommandOutput {
let template = r#"commit_id.short() ++ " " ++ description"#;
work_dir.run_jj(["log", "-T", template])
}