4336 lines · 138.5 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_git_hunk_header_section() {    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(        "src/lib.rs",        indoc! {"            fn unchanged() {                let value = 1;            }             pub async fn changed(value: i32) -> i32 {                value + 1            }        "},    );    work_dir.run_jj(["new"]).success();    work_dir.write_file(        "src/lib.rs",        indoc! {"            fn unchanged() {                let value = 1;            }             pub async fn changed(value: i32) -> i32 {                value + 2            }        "},    );     let output = work_dir.run_jj(["diff", "--git", "--context=0"]);    insta::assert_snapshot!(output, @"    diff --git a/src/lib.rs b/src/lib.rs    index a29875152a..dc32bb3132 100644    --- a/src/lib.rs    +++ b/src/lib.rs    @@ -6,1 +6,1 @@ pub async fn changed(value: i32) -> i32 {    -    value + 1    +    value + 2    [EOF]    ");} #[test]fn test_diff_git_hunk_header_added_section_uses_first_and_is_truncated() {    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("example.rs", "preamble\n");    work_dir.run_jj(["new"]).success();     let first_header = format!("fn first_{}() {{", "x".repeat(100));    work_dir.write_file(        "example.rs",        format!("preamble\n\n{first_header}\n}}\nfn second() {{\n}}\n"),    );     let output = work_dir.run_jj(["diff", "--git", "--context=0"]);    insta::assert_snapshot!(output, @"    diff --git a/example.rs b/example.rs    index 17a33febd0..381a95e747 100644    --- a/example.rs    +++ b/example.rs    @@ -1,0 +2,5 @@ fn first_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    +    +fn first_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx() {    +}    +fn second() {    +}    [EOF]    ");} #[test]fn test_diff_git_hunk_header_truncates_multibyte_symbol_by_bytes() {    let test_env = TestEnvironment::default();    test_env.run_jj_in(".", ["git", "init", "repo"]).success();    let work_dir = test_env.work_dir("repo");     let header = format!("fn example() {{ // {}", "€ ".repeat(100));    work_dir.write_file("example.rs", format!("{header}\n    1\n}}\n"));    work_dir.run_jj(["new"]).success();    work_dir.write_file("example.rs", format!("{header}\n    2\n}}\n"));     let output = work_dir.run_jj(["diff", "--git", "--context=0"]);    let hunk_header = output        .stdout        .raw()        .lines()        .find(|line| line.starts_with("@@"))        .unwrap();    let source_symbol = hunk_header.rsplit_once("@@ ").unwrap().1;    assert_eq!(        source_symbol,        format!("fn example() {{ // {}", "€ ".repeat(15))    );    assert_eq!(source_symbol.len(), 78);} #[test]fn test_diff_git_hunk_header_deletion_uses_deleted_section() {    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(        "src/lib.rs",        indoc! {"            fn deleted() {                let value = 1;            }             fn later() {}        "},    );    work_dir.run_jj(["new"]).success();    work_dir.write_file("src/lib.rs", "fn later() {}\n");     let output = work_dir.run_jj(["diff", "--git"]);    insta::assert_snapshot!(output, @"    diff --git a/src/lib.rs b/src/lib.rs    index 1c67155809..43e292937e 100644    --- a/src/lib.rs    +++ b/src/lib.rs    @@ -1,5 +1,1 @@ fn deleted() {    -fn deleted() {    -    let value = 1;    -}    -     fn later() {}    [EOF]    ");     let output = work_dir.run_jj(["diff", "--git", "--context=0"]);    insta::assert_snapshot!(output, @"    diff --git a/src/lib.rs b/src/lib.rs    index 1c67155809..43e292937e 100644    --- a/src/lib.rs    +++ b/src/lib.rs    @@ -1,4 +0,0 @@ fn deleted() {    -fn deleted() {    -    let value = 1;    -}    -    [EOF]    ");} #[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]

Lines 1–500 of 4336.