// 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 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; #[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: 25 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: 25 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, @" [38;5;3m<<diff header::Modified regular file file2:>>[39m [2m[38;5;1m<<diff context removed line_number:: 1>>[0m<<diff context:: >>[2m[38;5;2m<<diff context added line_number:: 1>>[0m<<diff context::: 1>> [38;5;1m<<diff removed line_number:: 2>>[39m<<diff:: >>[38;5;2m<<diff added line_number:: 2>>[39m<<diff::: >>[4m[38;5;1m<<diff removed token::2>>[38;5;2m<<diff added token::5>>[24m[39m<<diff::>> [2m[38;5;1m<<diff context removed line_number:: 3>>[0m<<diff context:: >>[2m[38;5;2m<<diff context added line_number:: 3>>[0m<<diff context::: 3>> [38;5;1m<<diff removed line_number:: 4>>[39m<<diff:: : >>[4m[38;5;1m<<diff removed token::4>>[24m[39m [38;5;3m<<diff header::Modified regular file file3 (file1 => file3):>>[39m [38;5;3m<<diff header::Modified regular file file4 (file2 => file4):>>[39m [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, @" [1m<<diff file_header::diff --git a/file2 b/file2>>[0m [1m<<diff file_header::index 94ebaf9001..1ffc51b472 100644>>[0m [1m<<diff file_header::--- a/file2>>[0m [1m<<diff file_header::+++ b/file2>>[0m [38;5;6m<<diff hunk_header::@@ -1,4 +1,3 @@>>[39m <<diff context:: 1>> [38;5;1m<<diff removed::->>[4m<<diff removed token::2>>[24m<<diff removed::>>[39m [38;5;2m<<diff added::+>>[4m<<diff added token::5>>[24m<<diff added::>>[39m <<diff context:: 3>> [38;5;1m<<diff removed::->>[4m<<diff removed token::4>>[24m[39m [1m<<diff file_header::diff --git a/file1 b/file3>>[0m [1m<<diff file_header::rename from file1>>[0m [1m<<diff file_header::rename to file3>>[0m [1m<<diff file_header::diff --git a/file2 b/file4>>[0m [1m<<diff file_header::copy from file2>>[0m [1m<<diff file_header::copy to file4>>[0m [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", "--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: 25 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: 12 Non-executable file became executable at file4: [EOF] "); let output = work_dir.run_jj(["diff", "-r@"]); insta::assert_snapshot!(output, @" Removed regular file file1: 1 : 2 Removed regular file file2: 1 : 1 Removed executable file file3: 1 : 2 Removed executable file file4: (empty) [EOF] "); let output = work_dir.run_jj(["diff", "-r@--", "--git"]); insta::assert_snapshot!(output, @" diff --git a/file1 b/file1 new file mode 100755 index 0000000000..e69de29bb2 diff --git a/file2 b/file2 new file mode 100755 index 0000000000..d00491fd7e --- /dev/null +++ b/file2 @@ -0,0 +1,1 @@ +1 diff --git a/file3 b/file3 new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/file3 @@ -0,0 +1,1 @@Lines 1–500 of 4030. Load more
// 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 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; #[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: 25 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: 25 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, @" [38;5;3m<<diff header::Modified regular file file2:>>[39m [2m[38;5;1m<<diff context removed line_number:: 1>>[0m<<diff context:: >>[2m[38;5;2m<<diff context added line_number:: 1>>[0m<<diff context::: 1>> [38;5;1m<<diff removed line_number:: 2>>[39m<<diff:: >>[38;5;2m<<diff added line_number:: 2>>[39m<<diff::: >>[4m[38;5;1m<<diff removed token::2>>[38;5;2m<<diff added token::5>>[24m[39m<<diff::>> [2m[38;5;1m<<diff context removed line_number:: 3>>[0m<<diff context:: >>[2m[38;5;2m<<diff context added line_number:: 3>>[0m<<diff context::: 3>> [38;5;1m<<diff removed line_number:: 4>>[39m<<diff:: : >>[4m[38;5;1m<<diff removed token::4>>[24m[39m [38;5;3m<<diff header::Modified regular file file3 (file1 => file3):>>[39m [38;5;3m<<diff header::Modified regular file file4 (file2 => file4):>>[39m [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, @" [1m<<diff file_header::diff --git a/file2 b/file2>>[0m [1m<<diff file_header::index 94ebaf9001..1ffc51b472 100644>>[0m [1m<<diff file_header::--- a/file2>>[0m [1m<<diff file_header::+++ b/file2>>[0m [38;5;6m<<diff hunk_header::@@ -1,4 +1,3 @@>>[39m <<diff context:: 1>> [38;5;1m<<diff removed::->>[4m<<diff removed token::2>>[24m<<diff removed::>>[39m [38;5;2m<<diff added::+>>[4m<<diff added token::5>>[24m<<diff added::>>[39m <<diff context:: 3>> [38;5;1m<<diff removed::->>[4m<<diff removed token::4>>[24m[39m [1m<<diff file_header::diff --git a/file1 b/file3>>[0m [1m<<diff file_header::rename from file1>>[0m [1m<<diff file_header::rename to file3>>[0m [1m<<diff file_header::diff --git a/file2 b/file4>>[0m [1m<<diff file_header::copy from file2>>[0m [1m<<diff file_header::copy to file4>>[0m [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", "--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: 25 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: 12 Non-executable file became executable at file4: [EOF] "); let output = work_dir.run_jj(["diff", "-r@"]); insta::assert_snapshot!(output, @" Removed regular file file1: 1 : 2 Removed regular file file2: 1 : 1 Removed executable file file3: 1 : 2 Removed executable file file4: (empty) [EOF] "); let output = work_dir.run_jj(["diff", "-r@--", "--git"]); insta::assert_snapshot!(output, @" diff --git a/file1 b/file1 new file mode 100755 index 0000000000..e69de29bb2 diff --git a/file2 b/file2 new file mode 100755 index 0000000000..d00491fd7e --- /dev/null +++ b/file2 @@ -0,0 +1,1 @@ +1 diff --git a/file3 b/file3 new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/file3 @@ -0,0 +1,1 @@