4185 lines · 134.3 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 indoc::indoc;use itertools::Itertools as _;use testutils::TestResult; use crate::common::CommandOutput;use crate::common::TestEnvironment;use crate::common::TestWorkDir;use crate::common::create_commit;use crate::common::create_commit_with_files;use crate::common::fake_diff_editor_path;use crate::common::to_toml_value; fn strip_ansi_escape_codes(output: String) -> String {    anstream::adapter::strip_str(&output).to_string()} #[test]fn test_diff_basic() {    let test_env = TestEnvironment::default();    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let work_dir = test_env.work_dir("repo");     work_dir.write_file("file1", "foo\n");    work_dir.write_file("file2", "1\n2\n3\n4\n");    work_dir.run_jj(["new"]).success();    work_dir.remove_file("file1");    work_dir.write_file("file2", "1\n5\n3\n");    work_dir.write_file("file3", "foo\n");    work_dir.write_file("file4", "1\n2\n3\n4\n");     let output = work_dir.run_jj(["diff"]);    insta::assert_snapshot!(output, @"    Modified regular file file2:       1    1: 1       2     : 2            2: 5       3    3: 3       4     : 4    Modified regular file file3 (file1 => file3):    Modified regular file file4 (file2 => file4):    [EOF]    ");     let output = work_dir.run_jj(["diff", "--context=0"]);    insta::assert_snapshot!(output, @"    Modified regular file file2:       1    1: 1       2     : 2            2: 5       3    3: 3       4     : 4    Modified regular file file3 (file1 => file3):    Modified regular file file4 (file2 => file4):    [EOF]    ");     let output = work_dir.run_jj(["diff", "--color=debug"]);    insta::assert_snapshot!(output, @"    <<diff color_words header::Modified regular file file2:>>    <<diff color_words context removed line_number::   1>><<diff color_words context:: >><<diff color_words context added line_number::   1>><<diff color_words context::: 1>>    <<diff color_words removed line_number::   2>><<diff color_words:: >><<diff color_words added line_number::   2>><<diff color_words::: >><<diff color_words removed token::2>><<diff color_words added token::5>><<diff color_words::>>    <<diff color_words context removed line_number::   3>><<diff color_words context:: >><<diff color_words context added line_number::   3>><<diff color_words context::: 3>>    <<diff color_words removed line_number::   4>><<diff color_words::     : >><<diff color_words removed token::4>>    <<diff color_words header::Modified regular file file3 (file1 => file3):>>    <<diff color_words header::Modified regular file file4 (file2 => file4):>>    [EOF]    ");     let output = work_dir.run_jj(["diff", "-s"]);    insta::assert_snapshot!(output, @"    M file2    R {file1 => file3}    C {file2 => file4}    [EOF]    ");     let output = work_dir.run_jj(["diff", "--types"]);    insta::assert_snapshot!(output, @"    FF file2    FF {file1 => file3}    FF {file2 => file4}    [EOF]    ");     let output = work_dir.run_jj(["diff", "--types", "glob:file[12]"]);    insta::assert_snapshot!(output, @"    F- file1    FF file2    [EOF]    ");     let template = r#"source.path() ++ ' => ' ++ target.path() ++ ' (' ++ status ++ ")\n""#;    let output = work_dir.run_jj(["diff", "-T", template]);    insta::assert_snapshot!(output, @"    file2 => file2 (modified)    file1 => file3 (renamed)    file2 => file4 (copied)    [EOF]    ");     let output = work_dir.run_jj(["diff", "--git", "file1"]);    insta::assert_snapshot!(output, @"    diff --git a/file1 b/file1    deleted file mode 100644    index 257cc5642c..0000000000    --- a/file1    +++ /dev/null    @@ -1,1 +0,0 @@    -foo    [EOF]    ");     let output = work_dir.run_jj(["diff", "--git"]);    insta::assert_snapshot!(output, @"    diff --git a/file2 b/file2    index 94ebaf9001..1ffc51b472 100644    --- a/file2    +++ b/file2    @@ -1,4 +1,3 @@     1    -2    +5     3    -4    diff --git a/file1 b/file3    rename from file1    rename to file3    diff --git a/file2 b/file4    copy from file2    copy to file4    [EOF]    ");     let output = work_dir.run_jj(["diff", "--git", "--context=0"]);    insta::assert_snapshot!(output, @"    diff --git a/file2 b/file2    index 94ebaf9001..1ffc51b472 100644    --- a/file2    +++ b/file2    @@ -2,1 +2,1 @@    -2    +5    @@ -4,1 +3,0 @@    -4    diff --git a/file1 b/file3    rename from file1    rename to file3    diff --git a/file2 b/file4    copy from file2    copy to file4    [EOF]    ");     let output = work_dir.run_jj(["diff", "--git", "--color=debug"]);    insta::assert_snapshot!(output, @"    <<diff git file_header::diff --git a/file2 b/file2>>    <<diff git file_header::index 94ebaf9001..1ffc51b472 100644>>    <<diff git file_header::--- a/file2>>    <<diff git file_header::+++ b/file2>>    <<diff git hunk_header::@@ -1,4 +1,3 @@>>    <<diff git context:: 1>>    <<diff git removed::->><<diff git removed token::2>><<diff git removed::>>    <<diff git added::+>><<diff git added token::5>><<diff git added::>>    <<diff git context:: 3>>    <<diff git removed::->><<diff git removed token::4>>    <<diff git file_header::diff --git a/file1 b/file3>>    <<diff git file_header::rename from file1>>    <<diff git file_header::rename to file3>>    <<diff git file_header::diff --git a/file2 b/file4>>    <<diff git file_header::copy from file2>>    <<diff git file_header::copy to file4>>    [EOF]    ");     let output = work_dir.run_jj(["diff", "-s", "--git"]);    insta::assert_snapshot!(output, @"    M file2    R {file1 => file3}    C {file2 => file4}    diff --git a/file2 b/file2    index 94ebaf9001..1ffc51b472 100644    --- a/file2    +++ b/file2    @@ -1,4 +1,3 @@     1    -2    +5     3    -4    diff --git a/file1 b/file3    rename from file1    rename to file3    diff --git a/file2 b/file4    copy from file2    copy to file4    [EOF]    ");     let output = work_dir.run_jj(["diff", "--git", "--config=diff.git.show-path-prefix=false"]);    insta::assert_snapshot!(output, @"    diff --git file2 file2    index 94ebaf9001..1ffc51b472 100644    --- file2    +++ file2    @@ -1,4 +1,3 @@     1    -2    +5     3    -4    diff --git file1 file3    rename from file1    rename to file3    diff --git file2 file4    copy from file2    copy to file4    [EOF]    ");     let output = work_dir.run_jj(["diff", "--stat"]);    insta::assert_snapshot!(output, @"    file2            | 3 +--    {file1 => file3} | 0    {file2 => file4} | 0    3 files changed, 1 insertion(+), 2 deletions(-)    [EOF]    ");     // Reverse-order diff    let output = work_dir.run_jj(["diff", "--to", "@-", "--git"]);    insta::assert_snapshot!(output, @"    diff --git a/file3 b/file1    rename from file3    rename to file1    diff --git a/file2 b/file2    index 1ffc51b472..94ebaf9001 100644    --- a/file2    +++ b/file2    @@ -1,3 +1,4 @@     1    -5    +2     3    +4    diff --git a/file4 b/file4    deleted file mode 100644    index 94ebaf9001..0000000000    --- a/file4    +++ /dev/null    @@ -1,4 +0,0 @@    -1    -2    -3    -4    [EOF]    ");     // Filter by glob pattern    let output = work_dir.run_jj(["diff", "-s", "glob:file[12]"]);    insta::assert_snapshot!(output, @"    D file1    M file2    [EOF]    ");     // Unmatched paths should generate warnings    let output = test_env.run_jj_in(        ".",        [            "diff",            "-Rrepo",            "-s",            "repo",       // matches directory            "repo/file1", // deleted in to_tree, but exists in from_tree            "repo/x",            "repo/y/z",        ],    );    insta::assert_snapshot!(output.normalize_backslash(), @"    M repo/file2    R repo/{file1 => file3}    C repo/{file2 => file4}    [EOF]    ------- stderr -------    Warning: No matching entries for paths: repo/x, repo/y/z    [EOF]    ");     // Unmodified paths shouldn't generate warnings    let output = work_dir.run_jj(["diff", "-s", "--from=@", "file2"]);    insta::assert_snapshot!(output, @"");     // --tool=:<builtin>    let output = work_dir.run_jj(["diff", "--tool=:summary", "--color-words", "file2"]);    insta::assert_snapshot!(output, @"    M file2    Modified regular file file2:       1    1: 1       2     : 2            2: 5       3    3: 3       4     : 4    [EOF]    ");    let output = work_dir.run_jj(["diff", "--tool=:git", "--stat", "file2"]);    insta::assert_snapshot!(output, @"    file2 | 3 +--    1 file changed, 1 insertion(+), 2 deletions(-)    diff --git a/file2 b/file2    index 94ebaf9001..1ffc51b472 100644    --- a/file2    +++ b/file2    @@ -1,4 +1,3 @@     1    -2    +5     3    -4    [EOF]    ");     // Bad combination    let output = work_dir.run_jj(["diff", "--summary", "--tool=:stat"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    Error: --tool=:stat cannot be used with --summary    [EOF]    [exit status: 2]    ");    let output = work_dir.run_jj(["diff", "--git", "--tool=:git"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    Error: --tool=:git cannot be used with --git    [EOF]    [exit status: 2]    ");    let output = work_dir.run_jj(["diff", "--git", "--tool=external"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    Error: --tool=external cannot be used with --git    [EOF]    [exit status: 2]    ");    let output = work_dir.run_jj(["diff", "-T''", "--summary"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    error: the argument '--template <TEMPLATE>' cannot be used with:      --summary      --stat      --types      --name-only     Usage: jj diff --template <TEMPLATE> [FILESETS]...     For more information, try '--help'.    [EOF]    [exit status: 2]    ");    let output = work_dir.run_jj(["diff", "-T''", "--git"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    error: the argument '--template <TEMPLATE>' cannot be used with:      --git      --color-words     Usage: jj diff --template <TEMPLATE> [FILESETS]...     For more information, try '--help'.    [EOF]    [exit status: 2]    ");    let output = work_dir.run_jj(["diff", "-T''", "--tool=:git"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    error: the argument '--template <TEMPLATE>' cannot be used with '--tool <TOOL>'     Usage: jj diff --template <TEMPLATE> [FILESETS]...     For more information, try '--help'.    [EOF]    [exit status: 2]    ");     // Bad builtin format    let output = work_dir.run_jj(["diff", "--config=ui.diff-formatter=:unknown"]);    insta::assert_snapshot!(output, @"    ------- stderr -------    Config error: Invalid type or value for ui.diff-formatter    Caused by: Invalid builtin diff format: unknown    For help, see https://docs.jj-vcs.dev/latest/config/ or use `jj help -k config`.    [EOF]    [exit status: 1]    ");} #[test]fn test_diff_empty() {    let test_env = TestEnvironment::default();    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let work_dir = test_env.work_dir("repo");     work_dir.write_file("file1", "");    let output = work_dir.run_jj(["diff"]);    insta::assert_snapshot!(output, @"    Added regular file file1:        (empty)    [EOF]    ");     work_dir.run_jj(["new"]).success();    work_dir.remove_file("file1");    let output = work_dir.run_jj(["diff"]);    insta::assert_snapshot!(output, @"    Removed regular file file1:        (empty)    [EOF]    ");     let output = work_dir.run_jj(["diff", "--stat"]);    insta::assert_snapshot!(output, @"    file1 | 0    1 file changed, 0 insertions(+), 0 deletions(-)    [EOF]    ");} #[test]fn test_diff_file_mode() {    let test_env = TestEnvironment::default();    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let work_dir = test_env.work_dir("repo");     // Test content+mode/mode-only changes of empty/non-empty files:    // - file1: ("",  x) -> ("2", n)  empty, content+mode    // - file2: ("1", x) -> ("1", n)  non-empty, mode-only    // - file3: ("1", n) -> ("2", x)  non-empty, content+mode    // - file4: ("",  n) -> ("",  x)  empty, mode-only     work_dir.write_file("file1", "");    work_dir.write_file("file2", "1\n");    work_dir.write_file("file3", "1\n");    work_dir.write_file("file4", "");    work_dir        .run_jj(["file", "chmod", "x", "file1", "file2"])        .success();     work_dir.run_jj(["new"]).success();    work_dir.write_file("file1", "2\n");    work_dir.write_file("file3", "2\n");    work_dir        .run_jj(["file", "chmod", "n", "file1", "file2"])        .success();    work_dir        .run_jj(["file", "chmod", "x", "file3", "file4"])        .success();     work_dir.run_jj(["new"]).success();    work_dir.remove_file("file1");    work_dir.remove_file("file2");    work_dir.remove_file("file3");    work_dir.remove_file("file4");     let output = work_dir.run_jj(["diff", "-r@--"]);    insta::assert_snapshot!(output, @"    Added executable file file1:        (empty)    Added executable file file2:            1: 1    Added regular file file3:            1: 1    Added regular file file4:        (empty)    [EOF]    ");    let output = work_dir.run_jj(["diff", "-r@-"]);    insta::assert_snapshot!(output, @"    Executable file became non-executable at file1:            1: 2    Executable file became non-executable at file2:    Non-executable file became executable at file3:       1     : 1            1: 2    Non-executable file became executable at file4:    [EOF]    ");    let output = work_dir.run_jj(["diff", "-r@"]);

Lines 1–500 of 4185.