1457 lines · 48.1 KB · Rust
RawDownload
// 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::Path;use std::path::PathBuf; use crate::common::CommandOutput;use crate::common::TestEnvironment; #[test]fn test_squash() {    let test_env = TestEnvironment::default();    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let repo_path = test_env.env_root().join("repo");     test_env        .run_jj_in(&repo_path, ["bookmark", "create", "-r@", "a"])        .success();    std::fs::write(repo_path.join("file1"), "a\n").unwrap();    test_env.run_jj_in(&repo_path, ["new"]).success();    test_env        .run_jj_in(&repo_path, ["bookmark", "create", "-r@", "b"])        .success();    std::fs::write(repo_path.join("file1"), "b\n").unwrap();    test_env.run_jj_in(&repo_path, ["new"]).success();    test_env        .run_jj_in(&repo_path, ["bookmark", "create", "-r@", "c"])        .success();    std::fs::write(repo_path.join("file1"), "c\n").unwrap();    // Test the setup    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r"    @  382c9bad7d42 c    ○  d5d59175b481 b    ○  184ddbcce5a9 a    ◆  000000000000 (empty)    [EOF]    ");     // Squashes the working copy into the parent by default    let output = test_env.run_jj_in(&repo_path, ["squash"]);    insta::assert_snapshot!(output, @r"    ------- stderr -------    Working copy  (@) now at: vruxwmqv f7bb78d8 (empty) (no description set)    Parent commit (@-)      : kkmpptxz 59f44460 b c | (no description set)    [EOF]    ");    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r"    @  f7bb78d8da62 (empty)    ○  59f4446070a0 b c    ○  184ddbcce5a9 a    ◆  000000000000 (empty)    [EOF]    ");    let output = test_env.run_jj_in(&repo_path, ["file", "show", "file1"]);    insta::assert_snapshot!(output, @r"    c    [EOF]    ");     // Can squash a given commit into its parent    test_env.run_jj_in(&repo_path, ["undo"]).success();    let output = test_env.run_jj_in(&repo_path, ["squash", "-r", "b"]);    insta::assert_snapshot!(output, @r"    ------- stderr -------    Rebased 1 descendant commits    Working copy  (@) now at: mzvwutvl 1d70f50a c | (no description set)    Parent commit (@-)      : qpvuntsm 9146bcc8 a b | (no description set)    [EOF]    ");    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r"    @  1d70f50afa6d c    ○  9146bcc8d996 a b    ◆  000000000000 (empty)    [EOF]    ");    let output = test_env.run_jj_in(&repo_path, ["file", "show", "file1", "-r", "b"]);    insta::assert_snapshot!(output, @r"    b    [EOF]    ");    let output = test_env.run_jj_in(&repo_path, ["file", "show", "file1"]);    insta::assert_snapshot!(output, @r"    c    [EOF]    ");     // Cannot squash a merge commit (because it's unclear which parent it should go    // into)    test_env.run_jj_in(&repo_path, ["undo"]).success();    test_env.run_jj_in(&repo_path, ["edit", "b"]).success();    test_env.run_jj_in(&repo_path, ["new"]).success();    test_env        .run_jj_in(&repo_path, ["bookmark", "create", "-r@", "d"])        .success();    std::fs::write(repo_path.join("file2"), "d\n").unwrap();    test_env.run_jj_in(&repo_path, ["new", "c", "d"]).success();    test_env        .run_jj_in(&repo_path, ["bookmark", "create", "-r@", "e"])        .success();    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r"    @    41219719ab5f e (empty)    ├─╮    │ ○  f86e2b3af3e3 d    ○ │  382c9bad7d42 c    ├─╯    ○  d5d59175b481 b    ○  184ddbcce5a9 a    ◆  000000000000 (empty)    [EOF]    ");    let output = test_env.run_jj_in(&repo_path, ["squash"]);    insta::assert_snapshot!(output, @r"    ------- 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    test_env.run_jj_in(&repo_path, ["new", "e"]).success();    std::fs::write(repo_path.join("file1"), "e\n").unwrap();    let output = test_env.run_jj_in(&repo_path, ["squash"]);    insta::assert_snapshot!(output, @r"    ------- stderr -------    Working copy  (@) now at: xlzxqlsl b50b843d (empty) (no description set)    Parent commit (@-)      : nmzmmopx 338cbc05 e | (no description set)    [EOF]    ");    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r"    @  b50b843d8555 (empty)    ○    338cbc05e4e6 e    ├─╮    │ ○  f86e2b3af3e3 d    ○ │  382c9bad7d42 c    ├─╯    ○  d5d59175b481 b    ○  184ddbcce5a9 a    ◆  000000000000 (empty)    [EOF]    ");    let output = test_env.run_jj_in(&repo_path, ["file", "show", "file1", "-r", "e"]);    insta::assert_snapshot!(output, @r"    e    [EOF]    ");} #[test]fn test_squash_partial() {    let mut test_env = TestEnvironment::default();    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let repo_path = test_env.env_root().join("repo");     test_env        .run_jj_in(&repo_path, ["bookmark", "create", "-r@", "a"])        .success();    std::fs::write(repo_path.join("file1"), "a\n").unwrap();    std::fs::write(repo_path.join("file2"), "a\n").unwrap();    test_env.run_jj_in(&repo_path, ["new"]).success();    test_env        .run_jj_in(&repo_path, ["bookmark", "create", "-r@", "b"])        .success();    std::fs::write(repo_path.join("file1"), "b\n").unwrap();    std::fs::write(repo_path.join("file2"), "b\n").unwrap();    test_env.run_jj_in(&repo_path, ["new"]).success();    test_env        .run_jj_in(&repo_path, ["bookmark", "create", "-r@", "c"])        .success();    std::fs::write(repo_path.join("file1"), "c\n").unwrap();    std::fs::write(repo_path.join("file2"), "c\n").unwrap();    // Test the setup    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r"    @  a0b1a272ebc4 c    ○  d117da276a0f b    ○  54d3c1c0e9fd a    ◆  000000000000 (empty)    [EOF]    ");     // If we don't make any changes in the diff-editor, the whole change is moved    // into the parent    let edit_script = test_env.set_up_fake_diff_editor();    std::fs::write(&edit_script, "dump JJ-INSTRUCTIONS instrs").unwrap();    let output = test_env.run_jj_in(&repo_path, ["squash", "-r", "b", "-i"]);    insta::assert_snapshot!(output, @r"    ------- stderr -------    Rebased 1 descendant commits    Working copy  (@) now at: mzvwutvl 3c633226 c | (no description set)    Parent commit (@-)      : qpvuntsm 38ffd8b9 a b | (no description set)    [EOF]    ");     insta::assert_snapshot!(        std::fs::read_to_string(test_env.env_root().join("instrs")).unwrap(), @r"    You are moving changes from: kkmpptxz d117da27 b | (no description set)    into commit: qpvuntsm 54d3c1c0 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(&test_env, &repo_path), @r"    @  3c6332267ea8 c    ○  38ffd8b98578 a b    ◆  000000000000 (empty)    [EOF]    ");    let output = test_env.run_jj_in(&repo_path, ["file", "show", "file1", "-r", "a"]);    insta::assert_snapshot!(output, @r"    b    [EOF]    ");     // Can squash only some changes in interactive mode    test_env.run_jj_in(&repo_path, ["undo"]).success();    std::fs::write(&edit_script, "reset file1").unwrap();    let output = test_env.run_jj_in(&repo_path, ["squash", "-r", "b", "-i"]);    insta::assert_snapshot!(output, @r"    ------- stderr -------    Rebased 2 descendant commits    Working copy  (@) now at: mzvwutvl 57c3cf20 c | (no description set)    Parent commit (@-)      : kkmpptxz c4925e01 b | (no description set)    [EOF]    ");    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r"    @  57c3cf20d0b1 c    ○  c4925e01d298 b    ○  1fc159063ed3 a    ◆  000000000000 (empty)    [EOF]    ");    let output = test_env.run_jj_in(&repo_path, ["file", "show", "file1", "-r", "a"]);    insta::assert_snapshot!(output, @r"    a    [EOF]    ");    let output = test_env.run_jj_in(&repo_path, ["file", "show", "file2", "-r", "a"]);    insta::assert_snapshot!(output, @r"    b    [EOF]    ");    let output = test_env.run_jj_in(&repo_path, ["file", "show", "file1", "-r", "b"]);    insta::assert_snapshot!(output, @r"    b    [EOF]    ");    let output = test_env.run_jj_in(&repo_path, ["file", "show", "file2", "-r", "b"]);    insta::assert_snapshot!(output, @r"    b    [EOF]    ");     // Can squash only some changes in non-interactive mode    test_env.run_jj_in(&repo_path, ["undo"]).success();    // Clear the script so we know it won't be used even without -i    std::fs::write(&edit_script, "").unwrap();    let output = test_env.run_jj_in(&repo_path, ["squash", "-r", "b", "file2"]);    insta::assert_snapshot!(output, @r"    ------- stderr -------    Rebased 2 descendant commits    Working copy  (@) now at: mzvwutvl 64d7ad7c c | (no description set)    Parent commit (@-)      : kkmpptxz 60a26452 b | (no description set)    [EOF]    ");    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r"    @  64d7ad7c43c1 c    ○  60a264527aee b    ○  7314692d32e3 a    ◆  000000000000 (empty)    [EOF]    ");    let output = test_env.run_jj_in(&repo_path, ["file", "show", "file1", "-r", "a"]);    insta::assert_snapshot!(output, @r"    a    [EOF]    ");    let output = test_env.run_jj_in(&repo_path, ["file", "show", "file2", "-r", "a"]);    insta::assert_snapshot!(output, @r"    b    [EOF]    ");    let output = test_env.run_jj_in(&repo_path, ["file", "show", "file1", "-r", "b"]);    insta::assert_snapshot!(output, @r"    b    [EOF]    ");    let output = test_env.run_jj_in(&repo_path, ["file", "show", "file2", "-r", "b"]);    insta::assert_snapshot!(output, @r"    b    [EOF]    ");     // If we specify only a non-existent file, then nothing changes.    test_env.run_jj_in(&repo_path, ["undo"]).success();    let output = test_env.run_jj_in(&repo_path, ["squash", "-r", "b", "nonexistent"]);    insta::assert_snapshot!(output, @r"    ------- stderr -------    Nothing changed.    [EOF]    ");     // We get a warning if we pass a positional argument that looks like a revset    test_env.run_jj_in(&repo_path, ["undo"]).success();    let output = test_env.run_jj_in(&repo_path, ["squash", "b"]);    insta::assert_snapshot!(output, @r#"    ------- stderr -------    Warning: The argument "b" is being interpreted as a fileset expression. To specify a revset, pass -r "b" instead.    Nothing changed.    [EOF]    "#);} #[test]fn test_squash_keep_emptied() {    let test_env = TestEnvironment::default();    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let repo_path = test_env.env_root().join("repo");     test_env        .run_jj_in(&repo_path, ["bookmark", "create", "-r@", "a"])        .success();    std::fs::write(repo_path.join("file1"), "a\n").unwrap();    test_env.run_jj_in(&repo_path, ["new"]).success();    test_env        .run_jj_in(&repo_path, ["bookmark", "create", "-r@", "b"])        .success();    std::fs::write(repo_path.join("file1"), "b\n").unwrap();    test_env.run_jj_in(&repo_path, ["new"]).success();    test_env        .run_jj_in(&repo_path, ["bookmark", "create", "-r@", "c"])        .success();    std::fs::write(repo_path.join("file1"), "c\n").unwrap();    // Test the setup     insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r"    @  382c9bad7d42 c    ○  d5d59175b481 b    ○  184ddbcce5a9 a    ◆  000000000000 (empty)    [EOF]    ");     let output = test_env.run_jj_in(&repo_path, ["squash", "-r", "b", "--keep-emptied"]);    insta::assert_snapshot!(output, @r"    ------- stderr -------    Rebased 2 descendant commits    Working copy  (@) now at: mzvwutvl 7ee7f18a c | (no description set)    Parent commit (@-)      : kkmpptxz 9490bd7f b | (empty) (no description set)    [EOF]    ");    // With --keep-emptied, b remains even though it is now empty.    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r"    @  7ee7f18a5223 c    ○  9490bd7f1e6a b (empty)    ○  53bf93080518 a    ◆  000000000000 (empty)    [EOF]    ");    let output = test_env.run_jj_in(&repo_path, ["file", "show", "file1", "-r", "a"]);    insta::assert_snapshot!(output, @r"    b    [EOF]    ");} #[test]fn test_squash_from_to() {    let test_env = TestEnvironment::default();    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let repo_path = test_env.env_root().join("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.    test_env        .run_jj_in(&repo_path, ["bookmark", "create", "-r@", "a"])        .success();    std::fs::write(repo_path.join("file1"), "a\n").unwrap();    std::fs::write(repo_path.join("file2"), "a\n").unwrap();    std::fs::write(repo_path.join("file3"), "a\n").unwrap();    test_env.run_jj_in(&repo_path, ["new"]).success();    test_env        .run_jj_in(&repo_path, ["bookmark", "create", "-r@", "b"])        .success();    std::fs::write(repo_path.join("file3"), "b\n").unwrap();    test_env.run_jj_in(&repo_path, ["new"]).success();    test_env        .run_jj_in(&repo_path, ["bookmark", "create", "-r@", "c"])        .success();    std::fs::write(repo_path.join("file1"), "c\n").unwrap();    test_env.run_jj_in(&repo_path, ["edit", "a"]).success();    test_env.run_jj_in(&repo_path, ["new"]).success();    test_env        .run_jj_in(&repo_path, ["bookmark", "create", "-r@", "d"])        .success();    std::fs::write(repo_path.join("file3"), "d\n").unwrap();    test_env.run_jj_in(&repo_path, ["new"]).success();    test_env        .run_jj_in(&repo_path, ["bookmark", "create", "-r@", "e"])        .success();    std::fs::write(repo_path.join("file2"), "e\n").unwrap();    test_env.run_jj_in(&repo_path, ["new"]).success();    test_env        .run_jj_in(&repo_path, ["bookmark", "create", "-r@", "f"])        .success();    std::fs::write(repo_path.join("file2"), "f\n").unwrap();    // Test the setup    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r"    @  a847ab4967fe f    ○  c2f9de87325d e    ○  e0dac715116f d    │ ○  59597b34a0d8 c    │ ○  12d6103dc0c8 b    ├─╯    ○  b7b767179c44 a    ◆  000000000000 (empty)    [EOF]    ");     // Errors out if source and destination are the same    let output = test_env.run_jj_in(&repo_path, ["squash", "--into", "@"]);    insta::assert_snapshot!(output, @r"    ------- stderr -------    Error: Source and destination cannot be the same    [EOF]    [exit status: 1]    ");     // Can squash from sibling, which results in the source being abandoned    let output = test_env.run_jj_in(&repo_path, ["squash", "--from", "c"]);    insta::assert_snapshot!(output, @r"    ------- stderr -------    Working copy  (@) now at: kmkuslsw b902d1dd f | (no description set)    Parent commit (@-)      : znkkpsqq c2f9de87 e | (no description set)    Added 0 files, modified 1 files, removed 0 files    [EOF]    ");    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r"    @  b902d1dd59d9 f    ○  c2f9de87325d e    ○  e0dac715116f d    │ ○  12d6103dc0c8 b c    ├─╯    ○  b7b767179c44 a    ◆  000000000000 (empty)    [EOF]    ");    // The change from the source has been applied    let output = test_env.run_jj_in(&repo_path, ["file", "show", "file1"]);    insta::assert_snapshot!(output, @r"    c    [EOF]    ");    // File `file2`, which was not changed in source, is unchanged    let output = test_env.run_jj_in(&repo_path, ["file", "show", "file2"]);    insta::assert_snapshot!(output, @r"    f    [EOF]    ");     // Can squash from ancestor    test_env.run_jj_in(&repo_path, ["undo"]).success();    let output = test_env.run_jj_in(&repo_path, ["squash", "--from", "@--"]);    insta::assert_snapshot!(output, @r"    ------- stderr -------    Working copy  (@) now at: kmkuslsw cfc5eb87 f | (no description set)    Parent commit (@-)      : znkkpsqq 4dc7c279 e | (no description set)    [EOF]    ");    // The change has been removed from the source (the change pointed to by 'd'    // became empty and was abandoned)    insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r"    @  cfc5eb876eb1 f    ○  4dc7c27994bd e    │ ○  59597b34a0d8 c

Lines 1–500 of 1457.