// Copyright 2022 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 std::path::PathBuf; use testutils::TestResult; use crate::common::CommandOutput;use crate::common::TestEnvironment;use crate::common::TestWorkDir; #[test]fn test_squash() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "repo"]).success(); let work_dir = test_env.work_dir("repo"); work_dir .run_jj(["bookmark", "create", "-r@", "a"]) .success(); work_dir.write_file("file1", "a\n"); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "b"]) .success(); work_dir.write_file("file1", "b\n"); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "c"]) .success(); work_dir.write_file("file1", "c\n"); // Test the setup insta::assert_snapshot!(get_log_output(&work_dir), @" @ 22be6c4e01da c ○ 75591b1896b4 b ○ e6086990958c a ◆ 000000000000 (empty) [EOF] "); let setup_opid = work_dir.current_operation_id(); // Squashes the working copy into the parent by default let output = work_dir.run_jj(["squash"]); insta::assert_snapshot!(output, @" ------- stderr ------- Working copy (@) now at: vruxwmqv 2cf02eb8 (empty) (no description set) Parent commit (@-) : kkmpptxz 9422c8d6 b c | (no description set) [EOF] "); insta::assert_snapshot!(get_log_output(&work_dir), @" @ 2cf02eb82d82 (empty) ○ 9422c8d6f294 b c ○ e6086990958c a ◆ 000000000000 (empty) [EOF] "); let output = work_dir.run_jj(["file", "show", "file1"]); insta::assert_snapshot!(output, @" c [EOF] "); // Can squash a given commit into its parent work_dir.run_jj(["op", "restore", &setup_opid]).success(); let output = work_dir.run_jj(["squash", "-r", "b"]); insta::assert_snapshot!(output, @" ------- stderr ------- Rebased 1 descendant commits Working copy (@) now at: mzvwutvl 441a7a3a c | (no description set) Parent commit (@-) : qpvuntsm 105931bf a b | (no description set) [EOF] "); insta::assert_snapshot!(get_log_output(&work_dir), @" @ 441a7a3a17b0 c ○ 105931bfedad a b ◆ 000000000000 (empty) [EOF] "); let output = work_dir.run_jj(["file", "show", "file1", "-r", "b"]); insta::assert_snapshot!(output, @" b [EOF] "); let output = work_dir.run_jj(["file", "show", "file1"]); insta::assert_snapshot!(output, @" c [EOF] "); // Cannot squash a merge commit (because it's unclear which parent it should go // into) work_dir.run_jj(["op", "restore", &setup_opid]).success(); work_dir.run_jj(["edit", "b"]).success(); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "d"]) .success(); work_dir.write_file("file2", "d\n"); work_dir.run_jj(["new", "c", "d"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "e"]) .success(); insta::assert_snapshot!(get_log_output(&work_dir), @" @ e05d4caaf6ce e (empty) ├─╮ │ ○ 9bb7863cfc78 d ○ │ 22be6c4e01da c ├─╯ ○ 75591b1896b4 b ○ e6086990958c a ◆ 000000000000 (empty) [EOF] "); let output = work_dir.run_jj(["squash"]); insta::assert_snapshot!(output, @" ------- stderr ------- Error: Cannot squash merge commits without a specified destination Hint: Use `--into` to specify which parent to squash into [EOF] [exit status: 1] "); // Can squash into a merge commit work_dir.run_jj(["new", "e"]).success(); work_dir.write_file("file1", "e\n"); let output = work_dir.run_jj(["squash"]); insta::assert_snapshot!(output, @" ------- stderr ------- Working copy (@) now at: xlzxqlsl 91a81249 (empty) (no description set) Parent commit (@-) : nmzmmopx 9155baf5 e | (no description set) [EOF] "); insta::assert_snapshot!(get_log_output(&work_dir), @" @ 91a81249954f (empty) ○ 9155baf5ced1 e ├─╮ │ ○ 9bb7863cfc78 d ○ │ 22be6c4e01da c ├─╯ ○ 75591b1896b4 b ○ e6086990958c a ◆ 000000000000 (empty) [EOF] "); let output = work_dir.run_jj(["file", "show", "file1", "-r", "e"]); insta::assert_snapshot!(output, @" e [EOF] ");} #[test]fn test_squash_partial() -> TestResult { let mut test_env = TestEnvironment::default(); let edit_script = test_env.set_up_fake_diff_editor(); test_env.run_jj_in(".", ["git", "init", "repo"]).success(); let work_dir = test_env.work_dir("repo"); work_dir .run_jj(["bookmark", "create", "-r@", "a"]) .success(); work_dir.write_file("file1", "a\n"); work_dir.write_file("file2", "a\n"); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "b"]) .success(); work_dir.write_file("file1", "b\n"); work_dir.write_file("file2", "b\n"); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "c"]) .success(); work_dir.write_file("file1", "c\n"); work_dir.write_file("file2", "c\n"); // Test the setup insta::assert_snapshot!(get_log_output(&work_dir), @" @ 87059ac9657b c ○ f2c9709f39e9 b ○ 64ea60be8d77 a ◆ 000000000000 (empty) [EOF] "); let start_op_id = work_dir.current_operation_id(); // If we don't make any changes in the diff-editor, the whole change is moved // into the parent std::fs::write(&edit_script, "dump JJ-INSTRUCTIONS instrs")?; let output = work_dir.run_jj(["squash", "-r", "b", "-i"]); insta::assert_snapshot!(output, @" ------- stderr ------- Rebased 1 descendant commits Working copy (@) now at: mzvwutvl 34484d82 c | (no description set) Parent commit (@-) : qpvuntsm 3141e675 a b | (no description set) [EOF] "); let instrs = std::fs::read_to_string(test_env.env_root().join("instrs"))?; insta::assert_snapshot!( instrs, @" You are moving changes from: kkmpptxz f2c9709f b | (no description set) into commit: qpvuntsm 64ea60be a | (no description set) The left side of the diff shows the contents of the parent commit. The right side initially shows the contents of the commit you're moving changes from. Adjust the right side until the diff shows the changes you want to move to the destination. If you don't make any changes, then all the changes from the source will be moved into the destination. "); insta::assert_snapshot!(get_log_output(&work_dir), @" @ 34484d825f47 c ○ 3141e67514f6 a b ◆ 000000000000 (empty) [EOF] "); let output = work_dir.run_jj(["file", "show", "file1", "-r", "a"]); insta::assert_snapshot!(output, @" b [EOF] "); // Can squash only some changes in interactive mode work_dir.run_jj(["op", "restore", &start_op_id]).success(); std::fs::write(&edit_script, "reset file1")?; let output = work_dir.run_jj(["squash", "-r", "b", "-i"]); insta::assert_snapshot!(output, @" ------- stderr ------- Rebased 2 descendant commits Working copy (@) now at: mzvwutvl 37e1a0ef c | (no description set) Parent commit (@-) : kkmpptxz b41e789d b | (no description set) [EOF] "); insta::assert_snapshot!(get_log_output(&work_dir), @" @ 37e1a0ef57ff c ○ b41e789df71c b ○ 3af17565155e a ◆ 000000000000 (empty) [EOF] "); let output = work_dir.run_jj(["file", "show", "file1", "-r", "a"]); insta::assert_snapshot!(output, @" a [EOF] "); let output = work_dir.run_jj(["file", "show", "file2", "-r", "a"]); insta::assert_snapshot!(output, @" b [EOF] "); let output = work_dir.run_jj(["file", "show", "file1", "-r", "b"]); insta::assert_snapshot!(output, @" b [EOF] "); let output = work_dir.run_jj(["file", "show", "file2", "-r", "b"]); insta::assert_snapshot!(output, @" b [EOF] "); // Can squash only some changes in non-interactive mode work_dir.run_jj(["op", "restore", &start_op_id]).success(); // Clear the script so we know it won't be used even without -i std::fs::write(&edit_script, "")?; let output = work_dir.run_jj(["squash", "-r", "b", "file2"]); insta::assert_snapshot!(output, @" ------- stderr ------- Rebased 2 descendant commits Working copy (@) now at: mzvwutvl 72ff256c c | (no description set) Parent commit (@-) : kkmpptxz dd056a92 b | (no description set) [EOF] "); insta::assert_snapshot!(get_log_output(&work_dir), @" @ 72ff256cd290 c ○ dd056a925eb3 b ○ cf083f1d9ccf a ◆ 000000000000 (empty) [EOF] "); let output = work_dir.run_jj(["file", "show", "file1", "-r", "a"]); insta::assert_snapshot!(output, @" a [EOF] "); let output = work_dir.run_jj(["file", "show", "file2", "-r", "a"]); insta::assert_snapshot!(output, @" b [EOF] "); let output = work_dir.run_jj(["file", "show", "file1", "-r", "b"]); insta::assert_snapshot!(output, @" b [EOF] "); let output = work_dir.run_jj(["file", "show", "file2", "-r", "b"]); insta::assert_snapshot!(output, @" b [EOF] "); // If we specify only a non-existent file, then nothing changes. work_dir.run_jj(["op", "restore", &start_op_id]).success(); let output = work_dir.run_jj(["squash", "-r", "b", "nonexistent"]); insta::assert_snapshot!(output, @" ------- stderr ------- Warning: No matching entries for paths: nonexistent Nothing changed. [EOF] "); // We get a warning if we pass a positional argument that looks like a revset work_dir.run_jj(["op", "restore", &start_op_id]).success(); let output = work_dir.run_jj(["squash", "b"]); insta::assert_snapshot!(output, @r#" ------- stderr ------- Warning: No matching entries for paths: b Warning: The argument "b" is being interpreted as a fileset expression. To specify a revset, pass -r "b" instead. Nothing changed. [EOF] "#); // No warning if we pass a positional argument does not parse as a revset work_dir.run_jj(["op", "restore", &start_op_id]).success(); let output = work_dir.run_jj(["squash", ".tmp"]); insta::assert_snapshot!(output, @" ------- stderr ------- Warning: No matching entries for paths: .tmp Nothing changed. [EOF] "); // we can use --interactive and fileset together work_dir.run_jj(["op", "restore", &start_op_id]).success(); work_dir.write_file("file3", "foo\n"); std::fs::write(&edit_script, "reset file1")?; let output = work_dir.run_jj(["squash", "-i", "file1", "file3"]); insta::assert_snapshot!(output, @" ------- stderr ------- Rebased 1 descendant commits Working copy (@) now at: mzvwutvl 3615d80e c | (no description set) Parent commit (@-) : kkmpptxz 037106c4 b | (no description set) [EOF] "); let output = work_dir.run_jj(["log", "-s"]); insta::assert_snapshot!(output, @" @ mzvwutvl test.user@example.com 2001-02-03 08:05:38 c 3615d80e │ (no description set) │ M file1 │ M file2 ○ kkmpptxz test.user@example.com 2001-02-03 08:05:38 b 037106c4 │ (no description set) │ M file1 │ M file2 │ A file3 ○ qpvuntsm test.user@example.com 2001-02-03 08:05:09 a 64ea60be │ (no description set) │ A file1 │ A file2 ◆ zzzzzzzz root() 00000000 [EOF] "); // Error if no changes selected in interactive mode work_dir.run_jj(["op", "restore", &start_op_id]).success(); std::fs::write(&edit_script, "reset file1\0reset file2")?; let output = work_dir.run_jj(["squash", "-r", "b", "-i"]); insta::assert_snapshot!(output, @" ------- stderr ------- Error: No changes selected [EOF] [exit status: 1] "); insta::assert_snapshot!(get_log_output(&work_dir), @" @ 87059ac9657b c ○ f2c9709f39e9 b ○ 64ea60be8d77 a ◆ 000000000000 (empty) [EOF] "); Ok(())} #[test]fn test_squash_keep_emptied() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "repo"]).success(); let work_dir = test_env.work_dir("repo"); work_dir .run_jj(["bookmark", "create", "-r@", "a"]) .success(); work_dir.write_file("file1", "a\n"); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "b"]) .success(); work_dir.write_file("file1", "b\n"); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "c"]) .success(); work_dir.write_file("file1", "c\n"); // Test the setup insta::assert_snapshot!(get_log_output(&work_dir), @" @ 22be6c4e01da c ○ 75591b1896b4 b ○ e6086990958c a ◆ 000000000000 (empty) [EOF] "); let output = work_dir.run_jj(["squash", "-r", "b", "--keep-emptied"]); insta::assert_snapshot!(output, @" ------- stderr ------- Rebased 2 descendant commits Working copy (@) now at: mzvwutvl 093590e0 c | (no description set) Parent commit (@-) : kkmpptxz 357946cf b | (empty) (no description set) [EOF] "); // With --keep-emptied, b remains even though it is now empty. insta::assert_snapshot!(get_log_output(&work_dir), @" @ 093590e044bd c ○ 357946cf85df b (empty) ○ 2269fb3b12f5 a ◆ 000000000000 (empty) [EOF] "); let output = work_dir.run_jj(["file", "show", "file1", "-r", "a"]); insta::assert_snapshot!(output, @" b [EOF] ");} #[test]fn test_squash_from_to() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "repo"]).success(); let work_dir = test_env.work_dir("repo"); // Create history like this: // F // | // E C // | | // D B // |/ // A // // When moving changes between e.g. C and F, we should not get unrelated changes // from B and D. work_dir .run_jj(["bookmark", "create", "-r@", "a"]) .success(); work_dir.write_file("file1", "a\n"); work_dir.write_file("file2", "a\n"); work_dir.write_file("file3", "a\n"); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "b"]) .success(); work_dir.write_file("file3", "b\n"); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "c"]) .success(); work_dir.write_file("file1", "c\n"); work_dir.run_jj(["edit", "a"]).success(); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "d"]) .success(); work_dir.write_file("file3", "d\n"); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "e"]) .success(); work_dir.write_file("file2", "e\n"); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "f"]) .success(); work_dir.write_file("file2", "f\n"); // Test the setupLines 1–500 of 2540. Load more
// Copyright 2022 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 std::path::PathBuf; use testutils::TestResult; use crate::common::CommandOutput; use crate::common::TestEnvironment; use crate::common::TestWorkDir; #[test] fn test_squash() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "repo"]).success(); let work_dir = test_env.work_dir("repo"); work_dir .run_jj(["bookmark", "create", "-r@", "a"]) .success(); work_dir.write_file("file1", "a\n"); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "b"]) .success(); work_dir.write_file("file1", "b\n"); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "c"]) .success(); work_dir.write_file("file1", "c\n"); // Test the setup insta::assert_snapshot!(get_log_output(&work_dir), @" @ 22be6c4e01da c ○ 75591b1896b4 b ○ e6086990958c a ◆ 000000000000 (empty) [EOF] "); let setup_opid = work_dir.current_operation_id(); // Squashes the working copy into the parent by default let output = work_dir.run_jj(["squash"]); insta::assert_snapshot!(output, @" ------- stderr ------- Working copy (@) now at: vruxwmqv 2cf02eb8 (empty) (no description set) Parent commit (@-) : kkmpptxz 9422c8d6 b c | (no description set) [EOF] "); insta::assert_snapshot!(get_log_output(&work_dir), @" @ 2cf02eb82d82 (empty) ○ 9422c8d6f294 b c ○ e6086990958c a ◆ 000000000000 (empty) [EOF] "); let output = work_dir.run_jj(["file", "show", "file1"]); insta::assert_snapshot!(output, @" c [EOF] "); // Can squash a given commit into its parent work_dir.run_jj(["op", "restore", &setup_opid]).success(); let output = work_dir.run_jj(["squash", "-r", "b"]); insta::assert_snapshot!(output, @" ------- stderr ------- Rebased 1 descendant commits Working copy (@) now at: mzvwutvl 441a7a3a c | (no description set) Parent commit (@-) : qpvuntsm 105931bf a b | (no description set) [EOF] "); insta::assert_snapshot!(get_log_output(&work_dir), @" @ 441a7a3a17b0 c ○ 105931bfedad a b ◆ 000000000000 (empty) [EOF] "); let output = work_dir.run_jj(["file", "show", "file1", "-r", "b"]); insta::assert_snapshot!(output, @" b [EOF] "); let output = work_dir.run_jj(["file", "show", "file1"]); insta::assert_snapshot!(output, @" c [EOF] "); // Cannot squash a merge commit (because it's unclear which parent it should go // into) work_dir.run_jj(["op", "restore", &setup_opid]).success(); work_dir.run_jj(["edit", "b"]).success(); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "d"]) .success(); work_dir.write_file("file2", "d\n"); work_dir.run_jj(["new", "c", "d"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "e"]) .success(); insta::assert_snapshot!(get_log_output(&work_dir), @" @ e05d4caaf6ce e (empty) ├─╮ │ ○ 9bb7863cfc78 d ○ │ 22be6c4e01da c ├─╯ ○ 75591b1896b4 b ○ e6086990958c a ◆ 000000000000 (empty) [EOF] "); let output = work_dir.run_jj(["squash"]); insta::assert_snapshot!(output, @" ------- stderr ------- Error: Cannot squash merge commits without a specified destination Hint: Use `--into` to specify which parent to squash into [EOF] [exit status: 1] "); // Can squash into a merge commit work_dir.run_jj(["new", "e"]).success(); work_dir.write_file("file1", "e\n"); let output = work_dir.run_jj(["squash"]); insta::assert_snapshot!(output, @" ------- stderr ------- Working copy (@) now at: xlzxqlsl 91a81249 (empty) (no description set) Parent commit (@-) : nmzmmopx 9155baf5 e | (no description set) [EOF] "); insta::assert_snapshot!(get_log_output(&work_dir), @" @ 91a81249954f (empty) ○ 9155baf5ced1 e ├─╮ │ ○ 9bb7863cfc78 d ○ │ 22be6c4e01da c ├─╯ ○ 75591b1896b4 b ○ e6086990958c a ◆ 000000000000 (empty) [EOF] "); let output = work_dir.run_jj(["file", "show", "file1", "-r", "e"]); insta::assert_snapshot!(output, @" e [EOF] "); } #[test] fn test_squash_partial() -> TestResult { let mut test_env = TestEnvironment::default(); let edit_script = test_env.set_up_fake_diff_editor(); test_env.run_jj_in(".", ["git", "init", "repo"]).success(); let work_dir = test_env.work_dir("repo"); work_dir .run_jj(["bookmark", "create", "-r@", "a"]) .success(); work_dir.write_file("file1", "a\n"); work_dir.write_file("file2", "a\n"); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "b"]) .success(); work_dir.write_file("file1", "b\n"); work_dir.write_file("file2", "b\n"); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "c"]) .success(); work_dir.write_file("file1", "c\n"); work_dir.write_file("file2", "c\n"); // Test the setup insta::assert_snapshot!(get_log_output(&work_dir), @" @ 87059ac9657b c ○ f2c9709f39e9 b ○ 64ea60be8d77 a ◆ 000000000000 (empty) [EOF] "); let start_op_id = work_dir.current_operation_id(); // If we don't make any changes in the diff-editor, the whole change is moved // into the parent std::fs::write(&edit_script, "dump JJ-INSTRUCTIONS instrs")?; let output = work_dir.run_jj(["squash", "-r", "b", "-i"]); insta::assert_snapshot!(output, @" ------- stderr ------- Rebased 1 descendant commits Working copy (@) now at: mzvwutvl 34484d82 c | (no description set) Parent commit (@-) : qpvuntsm 3141e675 a b | (no description set) [EOF] "); let instrs = std::fs::read_to_string(test_env.env_root().join("instrs"))?; insta::assert_snapshot!( instrs, @" You are moving changes from: kkmpptxz f2c9709f b | (no description set) into commit: qpvuntsm 64ea60be a | (no description set) The left side of the diff shows the contents of the parent commit. The right side initially shows the contents of the commit you're moving changes from. Adjust the right side until the diff shows the changes you want to move to the destination. If you don't make any changes, then all the changes from the source will be moved into the destination. "); insta::assert_snapshot!(get_log_output(&work_dir), @" @ 34484d825f47 c ○ 3141e67514f6 a b ◆ 000000000000 (empty) [EOF] "); let output = work_dir.run_jj(["file", "show", "file1", "-r", "a"]); insta::assert_snapshot!(output, @" b [EOF] "); // Can squash only some changes in interactive mode work_dir.run_jj(["op", "restore", &start_op_id]).success(); std::fs::write(&edit_script, "reset file1")?; let output = work_dir.run_jj(["squash", "-r", "b", "-i"]); insta::assert_snapshot!(output, @" ------- stderr ------- Rebased 2 descendant commits Working copy (@) now at: mzvwutvl 37e1a0ef c | (no description set) Parent commit (@-) : kkmpptxz b41e789d b | (no description set) [EOF] "); insta::assert_snapshot!(get_log_output(&work_dir), @" @ 37e1a0ef57ff c ○ b41e789df71c b ○ 3af17565155e a ◆ 000000000000 (empty) [EOF] "); let output = work_dir.run_jj(["file", "show", "file1", "-r", "a"]); insta::assert_snapshot!(output, @" a [EOF] "); let output = work_dir.run_jj(["file", "show", "file2", "-r", "a"]); insta::assert_snapshot!(output, @" b [EOF] "); let output = work_dir.run_jj(["file", "show", "file1", "-r", "b"]); insta::assert_snapshot!(output, @" b [EOF] "); let output = work_dir.run_jj(["file", "show", "file2", "-r", "b"]); insta::assert_snapshot!(output, @" b [EOF] "); // Can squash only some changes in non-interactive mode work_dir.run_jj(["op", "restore", &start_op_id]).success(); // Clear the script so we know it won't be used even without -i std::fs::write(&edit_script, "")?; let output = work_dir.run_jj(["squash", "-r", "b", "file2"]); insta::assert_snapshot!(output, @" ------- stderr ------- Rebased 2 descendant commits Working copy (@) now at: mzvwutvl 72ff256c c | (no description set) Parent commit (@-) : kkmpptxz dd056a92 b | (no description set) [EOF] "); insta::assert_snapshot!(get_log_output(&work_dir), @" @ 72ff256cd290 c ○ dd056a925eb3 b ○ cf083f1d9ccf a ◆ 000000000000 (empty) [EOF] "); let output = work_dir.run_jj(["file", "show", "file1", "-r", "a"]); insta::assert_snapshot!(output, @" a [EOF] "); let output = work_dir.run_jj(["file", "show", "file2", "-r", "a"]); insta::assert_snapshot!(output, @" b [EOF] "); let output = work_dir.run_jj(["file", "show", "file1", "-r", "b"]); insta::assert_snapshot!(output, @" b [EOF] "); let output = work_dir.run_jj(["file", "show", "file2", "-r", "b"]); insta::assert_snapshot!(output, @" b [EOF] "); // If we specify only a non-existent file, then nothing changes. work_dir.run_jj(["op", "restore", &start_op_id]).success(); let output = work_dir.run_jj(["squash", "-r", "b", "nonexistent"]); insta::assert_snapshot!(output, @" ------- stderr ------- Warning: No matching entries for paths: nonexistent Nothing changed. [EOF] "); // We get a warning if we pass a positional argument that looks like a revset work_dir.run_jj(["op", "restore", &start_op_id]).success(); let output = work_dir.run_jj(["squash", "b"]); insta::assert_snapshot!(output, @r#" ------- stderr ------- Warning: No matching entries for paths: b Warning: The argument "b" is being interpreted as a fileset expression. To specify a revset, pass -r "b" instead. Nothing changed. [EOF] "#); // No warning if we pass a positional argument does not parse as a revset work_dir.run_jj(["op", "restore", &start_op_id]).success(); let output = work_dir.run_jj(["squash", ".tmp"]); insta::assert_snapshot!(output, @" ------- stderr ------- Warning: No matching entries for paths: .tmp Nothing changed. [EOF] "); // we can use --interactive and fileset together work_dir.run_jj(["op", "restore", &start_op_id]).success(); work_dir.write_file("file3", "foo\n"); std::fs::write(&edit_script, "reset file1")?; let output = work_dir.run_jj(["squash", "-i", "file1", "file3"]); insta::assert_snapshot!(output, @" ------- stderr ------- Rebased 1 descendant commits Working copy (@) now at: mzvwutvl 3615d80e c | (no description set) Parent commit (@-) : kkmpptxz 037106c4 b | (no description set) [EOF] "); let output = work_dir.run_jj(["log", "-s"]); insta::assert_snapshot!(output, @" @ mzvwutvl test.user@example.com 2001-02-03 08:05:38 c 3615d80e │ (no description set) │ M file1 │ M file2 ○ kkmpptxz test.user@example.com 2001-02-03 08:05:38 b 037106c4 │ (no description set) │ M file1 │ M file2 │ A file3 ○ qpvuntsm test.user@example.com 2001-02-03 08:05:09 a 64ea60be │ (no description set) │ A file1 │ A file2 ◆ zzzzzzzz root() 00000000 [EOF] "); // Error if no changes selected in interactive mode work_dir.run_jj(["op", "restore", &start_op_id]).success(); std::fs::write(&edit_script, "reset file1\0reset file2")?; let output = work_dir.run_jj(["squash", "-r", "b", "-i"]); insta::assert_snapshot!(output, @" ------- stderr ------- Error: No changes selected [EOF] [exit status: 1] "); insta::assert_snapshot!(get_log_output(&work_dir), @" @ 87059ac9657b c ○ f2c9709f39e9 b ○ 64ea60be8d77 a ◆ 000000000000 (empty) [EOF] "); Ok(()) } #[test] fn test_squash_keep_emptied() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "repo"]).success(); let work_dir = test_env.work_dir("repo"); work_dir .run_jj(["bookmark", "create", "-r@", "a"]) .success(); work_dir.write_file("file1", "a\n"); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "b"]) .success(); work_dir.write_file("file1", "b\n"); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "c"]) .success(); work_dir.write_file("file1", "c\n"); // Test the setup insta::assert_snapshot!(get_log_output(&work_dir), @" @ 22be6c4e01da c ○ 75591b1896b4 b ○ e6086990958c a ◆ 000000000000 (empty) [EOF] "); let output = work_dir.run_jj(["squash", "-r", "b", "--keep-emptied"]); insta::assert_snapshot!(output, @" ------- stderr ------- Rebased 2 descendant commits Working copy (@) now at: mzvwutvl 093590e0 c | (no description set) Parent commit (@-) : kkmpptxz 357946cf b | (empty) (no description set) [EOF] "); // With --keep-emptied, b remains even though it is now empty. insta::assert_snapshot!(get_log_output(&work_dir), @" @ 093590e044bd c ○ 357946cf85df b (empty) ○ 2269fb3b12f5 a ◆ 000000000000 (empty) [EOF] "); let output = work_dir.run_jj(["file", "show", "file1", "-r", "a"]); insta::assert_snapshot!(output, @" b [EOF] "); } #[test] fn test_squash_from_to() { let test_env = TestEnvironment::default(); test_env.run_jj_in(".", ["git", "init", "repo"]).success(); let work_dir = test_env.work_dir("repo"); // Create history like this: // F // | // E C // | | // D B // |/ // A // // When moving changes between e.g. C and F, we should not get unrelated changes // from B and D. work_dir .run_jj(["bookmark", "create", "-r@", "a"]) .success(); work_dir.write_file("file1", "a\n"); work_dir.write_file("file2", "a\n"); work_dir.write_file("file3", "a\n"); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "b"]) .success(); work_dir.write_file("file3", "b\n"); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "c"]) .success(); work_dir.write_file("file1", "c\n"); work_dir.run_jj(["edit", "a"]).success(); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "d"]) .success(); work_dir.write_file("file3", "d\n"); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "e"]) .success(); work_dir.write_file("file2", "e\n"); work_dir.run_jj(["new"]).success(); work_dir .run_jj(["bookmark", "create", "-r@", "f"]) .success(); work_dir.write_file("file2", "f\n"); // Test the setup