diff --git a/cli/src/commands/diff.rs b/cli/src/commands/diff.rs index 99ae0661390..294a191fd1b 100644 --- a/cli/src/commands/diff.rs +++ b/cli/src/commands/diff.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use itertools::Itertools as _; use jj_lib::rewrite::merge_commit_trees; use tracing::instrument; @@ -76,9 +77,8 @@ pub(crate) fn cmd_diff( from_tree = merge_commit_trees(workspace_command.repo().as_ref(), &parents)?; to_tree = commit.tree()? } - let matcher = workspace_command - .parse_file_patterns(&args.paths)? - .to_matcher(); + let fileset_expression = workspace_command.parse_file_patterns(&args.paths)?; + let matcher = fileset_expression.to_matcher(); let diff_formats = diff_formats_for(command.settings(), &args.format)?; ui.request_pager(); show_diff( @@ -90,5 +90,19 @@ pub(crate) fn cmd_diff( matcher.as_ref(), &diff_formats, )?; + + let unmatched_explicit_paths = fileset_expression + .explicit_paths() + .filter(|path| from_tree.path_value(path).is_absent()) + .filter(|path| to_tree.path_value(path).is_absent()) + .map(|path| workspace_command.format_file_path(path)) + .collect_vec(); + if !unmatched_explicit_paths.is_empty() { + writeln!( + ui.warning_default(), + "No matching entries for paths: {}", + unmatched_explicit_paths.join(", ") + )?; + } Ok(()) } diff --git a/cli/tests/test_diff_command.rs b/cli/tests/test_diff_command.rs index dac18276a3b..b4ec88c3899 100644 --- a/cli/tests/test_diff_command.rs +++ b/cli/tests/test_diff_command.rs @@ -149,6 +149,33 @@ fn test_diff_basic() { file3 | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) "###); + + // Unmatched paths should be warned + let (stdout, stderr) = test_env.jj_cmd_ok( + test_env.env_root(), + &[ + "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!(stdout.replace('\\', "/"), @r###" + D repo/file1 + M repo/file2 + A repo/file3 + "###); + insta::assert_snapshot!(stderr.replace('\\', "/"), @r###" + Warning: No matching entries for paths: repo/x, repo/y/z + "###); + + // Unmodified paths shouldn't be warned + let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["diff", "-s", "--from=@", "file2"]); + insta::assert_snapshot!(stdout, @""); + insta::assert_snapshot!(stderr, @""); } #[test]