1137 lines · 35.8 KB · Rust
RawDownload
// Copyright 2024 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 testutils::TestResult; use crate::common::CommandOutput;use crate::common::TestEnvironment;use crate::common::TestWorkDir; #[test]fn test_absorb_simple() {    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(["describe", "-m0"]).success();    work_dir.write_file("file1", "");     work_dir.run_jj(["new", "-m1"]).success();    work_dir.write_file("file1", "1a\n1b\n");     work_dir.run_jj(["new", "-m2"]).success();    work_dir.write_file("file1", "1a\n1b\n2a\n2b\n");     // Empty commit    work_dir.run_jj(["new"]).success();    let output = work_dir.run_jj(["absorb"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    Nothing changed.    [EOF]    ");     // Insert first and last lines    work_dir.write_file("file1", "1X\n1a\n1b\n2a\n2b\n2Z\n");    let output = work_dir.run_jj(["absorb"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    Absorbed changes into 2 revisions:      zsuskuln 95568809 2      kkmpptxz bd7d4016 1    Working copy  (@) now at: yqosqzyt 977269ac (empty) (no description set)    Parent commit (@-)      : zsuskuln 95568809 2    [EOF]    ");     // Modify middle line in hunk    work_dir.write_file("file1", "1X\n1A\n1b\n2a\n2b\n2Z\n");    let output = work_dir.run_jj(["absorb"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    Absorbed changes into 1 revisions:      kkmpptxz 5810eb0f 1    Rebased 1 descendant commits.    Working copy  (@) now at: vruxwmqv 48c7d8fa (empty) (no description set)    Parent commit (@-)      : zsuskuln 8edd60a2 2    [EOF]    ");     // Remove middle line from hunk    work_dir.write_file("file1", "1X\n1A\n1b\n2a\n2Z\n");    let output = work_dir.run_jj(["absorb"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    Absorbed changes into 1 revisions:      zsuskuln dd109863 2    Working copy  (@) now at: yostqsxw 7482f74b (empty) (no description set)    Parent commit (@-)      : zsuskuln dd109863 2    [EOF]    ");     // Insert ambiguous line in between    work_dir.write_file("file1", "1X\n1A\n1b\nY\n2a\n2Z\n");    let output = work_dir.run_jj(["absorb"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    Nothing changed.    [EOF]    ");     insta::assert_snapshot!(get_diffs(&work_dir, "mutable()"), @"    @  yostqsxw bde51bc9 (no description set)    │  diff --git a/file1 b/file1    │  index 8653ca354d..88eb438902 100644    │  --- a/file1    │  +++ b/file1    │  @@ -1,5 +1,6 @@ Y    │   1X    │   1A    │   1b    │  +Y    │   2a    │   2Z    ○  zsuskuln dd109863 2    │  diff --git a/file1 b/file1    │  index ed237b5112..8653ca354d 100644    │  --- a/file1    │  +++ b/file1    │  @@ -1,3 +1,5 @@    │   1X    │   1A    │   1b    │  +2a    │  +2Z    ○  kkmpptxz 5810eb0f 1    │  diff --git a/file1 b/file1    │  index e69de29bb2..ed237b5112 100644    │  --- a/file1    │  +++ b/file1    │  @@ -0,0 +1,3 @@    │  +1X    │  +1A    │  +1b    ○  qpvuntsm 6a446874 0    │  diff --git a/file1 b/file1    ~  new file mode 100644       index 0000000000..e69de29bb2    [EOF]    ");    insta::assert_snapshot!(get_evolog(&work_dir, "subject(1)"), @"    ○    kkmpptxz 5810eb0f 1    ├─╮    │ ○  yqosqzyt/0 39b42898 (hidden) (no description set)    │ ○  yqosqzyt/1 977269ac (hidden) (empty) (no description set)    ○    kkmpptxz/1 bd7d4016 (hidden) 1    ├─╮    │ ○  mzvwutvl/0 0b307741 (hidden) (no description set)    │ ○  mzvwutvl/1 f2709b4e (hidden) (empty) (no description set)    ○  kkmpptxz/2 1553c5e8 (hidden) 1    ○  kkmpptxz/3 eb943711 (hidden) (empty) 1    [EOF]    ");    insta::assert_snapshot!(get_evolog(&work_dir, "subject(2)"), @"    ○    zsuskuln dd109863 2    ├─╮    │ ○  vruxwmqv/0 761492a8 (hidden) (no description set)    │ ○  vruxwmqv/1 48c7d8fa (hidden) (empty) (no description set)    ○  zsuskuln/1 8edd60a2 (hidden) 2    ○    zsuskuln/2 95568809 (hidden) 2    ├─╮    │ ○  mzvwutvl/0 0b307741 (hidden) (no description set)    │ ○  mzvwutvl/1 f2709b4e (hidden) (empty) (no description set)    ○  zsuskuln/3 36fad385 (hidden) 2    ○  zsuskuln/4 561fbce9 (hidden) (empty) 2    [EOF]    ");} #[test]fn test_absorb_replace_single_line_hunk() {    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(["describe", "-m1"]).success();    work_dir.write_file("file1", "1a\n");     work_dir.run_jj(["new", "-m2"]).success();    work_dir.write_file("file1", "2a\n1a\n2b\n");     // Replace single-line hunk, which produces a conflict right now. If our    // merge logic were based on interleaved delta, the hunk would be applied    // cleanly.    work_dir.run_jj(["new"]).success();    work_dir.write_file("file1", "2a\n1A\n2b\n");    let output = work_dir.run_jj(["absorb"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    Absorbed changes into 1 revisions:      qpvuntsm 125fba68 (conflict) 1    Rebased 1 descendant commits.    Working copy  (@) now at: mzvwutvl deeb043a (empty) (no description set)    Parent commit (@-)      : kkmpptxz 732472fb 2    New conflicts appeared in 1 commits:      qpvuntsm 125fba68 (conflict) 1    Hint: To resolve the conflicts, start by creating a commit on top of    the conflicted commit:      jj new qpvuntsm    Then use `jj resolve`, or edit the conflict markers in the file directly.    Once the conflicts are resolved, you can inspect the result with `jj diff`.    Then run `jj squash` to move the resolution into the conflicted commit.    [EOF]    ");     insta::assert_snapshot!(get_diffs(&work_dir, "mutable()"), @r#"    @  mzvwutvl deeb043a (empty) (no description set)    ○  kkmpptxz 732472fb 2    │  diff --git a/file1 b/file1    │  index 0000000000..2f87e8e465 100644    │  --- a/file1    │  +++ b/file1    │  @@ -1,11 +1,3 @@    │  -<<<<<<< conflict 1 of 1    │  -%%%%%%% diff from: kkmpptxz 9d700628 "2" (parents of absorbed revision)    │  -\\\\\\\        to: qpvuntsm aa6cb9bc "1" (absorb destination)    │  --2a    │  - 1a    │  --2b    │  -+++++++ absorbed changes (from zsuskuln 5d926f12)    │   2a    │   1A    │   2b    │  ->>>>>>> conflict 1 of 1 ends    ×  qpvuntsm 125fba68 (conflict) 1    │  diff --git a/file1 b/file1    ~  new file mode 100644       index 0000000000..0000000000       --- /dev/null       +++ b/file1       @@ -0,0 +1,11 @@       +<<<<<<< conflict 1 of 1       +%%%%%%% diff from: kkmpptxz 9d700628 "2" (parents of absorbed revision)       +\\\\\\\        to: qpvuntsm aa6cb9bc "1" (absorb destination)       +-2a       + 1a       +-2b       ++++++++ absorbed changes (from zsuskuln 5d926f12)       +2a       +1A       +2b       +>>>>>>> conflict 1 of 1 ends    [EOF]    "#);} #[test]fn test_absorb_merge() {    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(["describe", "-m0"]).success();    work_dir.write_file("file1", "0a\n");     work_dir.run_jj(["new", "-m1"]).success();    work_dir.write_file("file1", "1a\n1b\n0a\n");     work_dir.run_jj(["new", "-m2", "subject(0)"]).success();    work_dir.write_file("file1", "0a\n2a\n2b\n");     let output = work_dir.run_jj(["new", "-m3", "subject(1)", "subject(2)"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    Working copy  (@) now at: mzvwutvl 42875bf7 (empty) 3    Parent commit (@-)      : kkmpptxz 9c66f62f 1    Parent commit (@-)      : zsuskuln 6a3dcbcf 2    Added 0 files, modified 1 files, removed 0 files    [EOF]    ");     // Modify first and last lines, absorb from merge    work_dir.write_file("file1", "1A\n1b\n0a\n2a\n2B\n");    let output = work_dir.run_jj(["absorb"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    Absorbed changes into 2 revisions:      zsuskuln a6fde7ea 2      kkmpptxz 00ecc958 1    Rebased 1 descendant commits.    Working copy  (@) now at: mzvwutvl 30499858 (empty) 3    Parent commit (@-)      : kkmpptxz 00ecc958 1    Parent commit (@-)      : zsuskuln a6fde7ea 2    [EOF]    ");     // Add hunk to merge revision    work_dir.write_file("file2", "3a\n");     // Absorb into merge    work_dir.run_jj(["new"]).success();    work_dir.write_file("file2", "3A\n");    let output = work_dir.run_jj(["absorb"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    Absorbed changes into 1 revisions:      mzvwutvl faf778a4 3    Working copy  (@) now at: vruxwmqv cec519a1 (empty) (no description set)    Parent commit (@-)      : mzvwutvl faf778a4 3    [EOF]    ");     insta::assert_snapshot!(get_diffs(&work_dir, "mutable()"), @"    @  vruxwmqv cec519a1 (empty) (no description set)    ○    mzvwutvl faf778a4 3    ├─╮  diff --git a/file2 b/file2    │ │  new file mode 100644    │ │  index 0000000000..44442d2d7b    │ │  --- /dev/null    │ │  +++ b/file2    │ │  @@ -0,0 +1,1 @@    │ │  +3A    │ ○  zsuskuln a6fde7ea 2    │ │  diff --git a/file1 b/file1    │ │  index eb6e8821f1..4907935b9f 100644    │ │  --- a/file1    │ │  +++ b/file1    │ │  @@ -1,1 +1,3 @@    │ │   0a    │ │  +2a    │ │  +2B    ○ │  kkmpptxz 00ecc958 1    ├─╯  diff --git a/file1 b/file1    │    index eb6e8821f1..902dd8ef13 100644    │    --- a/file1    │    +++ b/file1    │    @@ -1,1 +1,3 @@    │    +1A    │    +1b    │     0a    ○  qpvuntsm d4f07be5 0    │  diff --git a/file1 b/file1    ~  new file mode 100644       index 0000000000..eb6e8821f1       --- /dev/null       +++ b/file1       @@ -0,0 +1,1 @@       +0a    [EOF]    ");} #[test]fn test_absorb_discardable_merge_with_descendant() {    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(["describe", "-m0"]).success();    work_dir.write_file("file1", "0a\n");     work_dir.run_jj(["new", "-m1"]).success();    work_dir.write_file("file1", "1a\n1b\n0a\n");     work_dir.run_jj(["new", "-m2", "subject(0)"]).success();    work_dir.write_file("file1", "0a\n2a\n2b\n");     let output = work_dir.run_jj(["new", "subject(1)", "subject(2)"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    Working copy  (@) now at: mzvwutvl ad00b91a (empty) (no description set)    Parent commit (@-)      : kkmpptxz 9c66f62f 1    Parent commit (@-)      : zsuskuln 6a3dcbcf 2    Added 0 files, modified 1 files, removed 0 files    [EOF]    ");     // Modify first and last lines in the merge commit    work_dir.write_file("file1", "1A\n1b\n0a\n2a\n2B\n");    // Add new commit on top    work_dir.run_jj(["new", "-m3"]).success();    work_dir.write_file("file2", "3a\n");    // Then absorb the merge commit    let output = work_dir.run_jj(["absorb", "--from=@-"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    Absorbed changes into 2 revisions:      zsuskuln a6cd8e87 2      kkmpptxz 98b7d214 1    Rebased 1 descendant commits.    Working copy  (@) now at: royxmykx df946e9b 3    Parent commit (@-)      : kkmpptxz 98b7d214 1    Parent commit (@-)      : zsuskuln a6cd8e87 2    [EOF]    ");     insta::assert_snapshot!(get_diffs(&work_dir, "mutable()"), @"    @    royxmykx df946e9b 3    ├─╮  diff --git a/file2 b/file2    │ │  new file mode 100644    │ │  index 0000000000..31cd755d20    │ │  --- /dev/null    │ │  +++ b/file2    │ │  @@ -0,0 +1,1 @@    │ │  +3a    │ ○  zsuskuln a6cd8e87 2    │ │  diff --git a/file1 b/file1    │ │  index eb6e8821f1..4907935b9f 100644    │ │  --- a/file1    │ │  +++ b/file1    │ │  @@ -1,1 +1,3 @@    │ │   0a    │ │  +2a    │ │  +2B    ○ │  kkmpptxz 98b7d214 1    ├─╯  diff --git a/file1 b/file1    │    index eb6e8821f1..902dd8ef13 100644    │    --- a/file1    │    +++ b/file1    │    @@ -1,1 +1,3 @@    │    +1A    │    +1b    │     0a    ○  qpvuntsm d4f07be5 0    │  diff --git a/file1 b/file1    ~  new file mode 100644       index 0000000000..eb6e8821f1       --- /dev/null       +++ b/file1       @@ -0,0 +1,1 @@       +0a    [EOF]    ");} #[test]fn test_absorb_conflict() {    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(["describe", "-m1"]).success();    work_dir.write_file("file1", "1a\n1b\n");     work_dir.run_jj(["new", "root()"]).success();    work_dir.write_file("file1", "2a\n2b\n");    let output = work_dir.run_jj(["rebase", "-r@", "-dsubject(1)"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    Rebased 1 commits to destination.    Working copy  (@) now at: kkmpptxz 628e2b00 (conflict) (no description set)    Parent commit (@-)      : qpvuntsm e35bcaff 1    Added 0 files, modified 1 files, removed 0 files    Warning: There are unresolved conflicts at these paths:    file1    2-sided conflict    New conflicts appeared in 1 commits:      kkmpptxz 628e2b00 (conflict) (no description set)    Hint: To resolve the conflicts, start by creating a commit on top of    the conflicted commit:      jj new kkmpptxz    Then use `jj resolve`, or edit the conflict markers in the file directly.    Once the conflicts are resolved, you can inspect the result with `jj diff`.    Then run `jj squash` to move the resolution into the conflicted commit.    [EOF]    ");     let conflict_content = work_dir.read_file("file1");    insta::assert_snapshot!(conflict_content, @r#"    <<<<<<< conflict 1 of 1    %%%%%%% diff from: zzzzzzzz 00000000 (parents of rebased revision)    \\\\\\\        to: qpvuntsm e35bcaff "1" (rebase destination)    +1a    +1b    +++++++ kkmpptxz e05db987 (rebased revision)    2a    2b    >>>>>>> conflict 1 of 1 ends    "#);     // Cannot absorb from conflict    let output = work_dir.run_jj(["absorb"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    Warning: Skipping file1: Is a conflict    Nothing changed.    [EOF]    ");     // Cannot absorb from resolved conflict    work_dir.run_jj(["new"]).success();    work_dir.write_file("file1", "1A\n1b\n2a\n2B\n");    let output = work_dir.run_jj(["absorb"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    Warning: Skipping file1: Is a conflict    Nothing changed.    [EOF]    ");} #[test]fn test_absorb_deleted_file() {    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(["describe", "-m1"]).success();    work_dir.write_file("file1", "1a\n");    work_dir.write_file("file2", "1a\n");    work_dir.write_file("file3", "");     work_dir.run_jj(["new"]).success();    work_dir.remove_file("file1");    work_dir.write_file("file2", ""); // emptied    work_dir.remove_file("file3"); // no content change     // Since the destinations are chosen based on content diffs, file3 cannot be    // absorbed.    let output = work_dir.run_jj(["absorb"]);    insta::assert_snapshot!(output, @"

Lines 1–500 of 1137.