2540 lines · 78.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::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, @r"    ------- 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, @r"    ------- 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, @r"    ------- 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, @r"    ------- 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, @r"    ------- 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, @r"    ------- 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

Lines 1–500 of 2540.