diff mbox series

[v2,1/4] diff --no-index: refuse to compare stdin to a directory

Message ID 5e65a15223bc42293516308eb31ade5395609c55.1688586536.git.phillip.wood@dunelm.org.uk (mailing list archive)
State Accepted
Commit 498198453dbb8ae46becbc83a1ef0979a0eb805d
Headers show
Series diff --no-index: support reading from named pipes | expand

Commit Message

Phillip Wood July 5, 2023, 7:49 p.m. UTC
From: Phillip Wood <phillip.wood@dunelm.org.uk>

When the user runs

    git diff --no-index file directory

we follow the behavior of POSIX diff and rewrite the arguments as

    git diff --no-index file directory/file

Doing that when "file" is "-" (which means "read from stdin") does not
make sense so we should error out if the user asks us to compare "-" to
a directory. This matches the behavior of GNU diff and diff on *BSD.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
---
 diff-no-index.c          | 12 +++++++-----
 t/t4053-diff-no-index.sh |  5 +++++
 2 files changed, 12 insertions(+), 5 deletions(-)

Comments

Junio C Hamano July 5, 2023, 9:17 p.m. UTC | #1
Phillip Wood <phillip.wood123@gmail.com> writes:

> From: Phillip Wood <phillip.wood@dunelm.org.uk>
>
> When the user runs
>
>     git diff --no-index file directory
>
> we follow the behavior of POSIX diff and rewrite the arguments as
>
>     git diff --no-index file directory/file
>
> Doing that when "file" is "-" (which means "read from stdin") does not
> make sense so we should error out if the user asks us to compare "-" to
> a directory. This matches the behavior of GNU diff and diff on *BSD.

"git diff --no-index directory file" would also be the same way.

Makes sense.

> -	if (path[0] == file_from_standard_input ||
> -	    path[1] == file_from_standard_input)
> -		return;
> -	isdir0 = is_directory(path[0]);
> -	isdir1 = is_directory(path[1]);

We used to silently did nonsense, I guess.

> +	isdir0 = path[0] != file_from_standard_input && is_directory(path[0]);
> +	isdir1 = path[1] != file_from_standard_input && is_directory(path[1]);
> +
> +	if ((path[0] == file_from_standard_input && isdir1) ||
> +	    (isdir0 && path[1] == file_from_standard_input))
> +		die(_("cannot compare stdin to a directory"));

OK.  It is much better than turning "diff - D" into "diff - D/-".
If D were a missing or a misspelt directory name, the rest of the
function will just leave the original intact and let comparison
between the standard input and D that does not exist, and will fail
correctly anyway.  Good.

>  	if (isdir0 == isdir1)
>  		return;
>  	if (isdir0) {
> diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh
> index 4e9fa0403d..5bfb282e98 100755
> --- a/t/t4053-diff-no-index.sh
> +++ b/t/t4053-diff-no-index.sh
> @@ -205,4 +205,9 @@ test_expect_success POSIXPERM,SYMLINKS 'diff --no-index normalizes: mode not lik
>  	test_cmp expected actual
>  '
>  
> +test_expect_success 'diff --no-index refuses to diff stdin and a directory' '
> +	test_must_fail git diff --no-index -- - a </dev/null 2>err &&
> +	grep "fatal: cannot compare stdin to a directory" err
> +'
> +
>  test_done
diff mbox series

Patch

diff --git a/diff-no-index.c b/diff-no-index.c
index 4296940f90..77462ac2a9 100644
--- a/diff-no-index.c
+++ b/diff-no-index.c
@@ -218,11 +218,13 @@  static void fixup_paths(const char **path, struct strbuf *replacement)
 {
 	unsigned int isdir0, isdir1;
 
-	if (path[0] == file_from_standard_input ||
-	    path[1] == file_from_standard_input)
-		return;
-	isdir0 = is_directory(path[0]);
-	isdir1 = is_directory(path[1]);
+	isdir0 = path[0] != file_from_standard_input && is_directory(path[0]);
+	isdir1 = path[1] != file_from_standard_input && is_directory(path[1]);
+
+	if ((path[0] == file_from_standard_input && isdir1) ||
+	    (isdir0 && path[1] == file_from_standard_input))
+		die(_("cannot compare stdin to a directory"));
+
 	if (isdir0 == isdir1)
 		return;
 	if (isdir0) {
diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh
index 4e9fa0403d..5bfb282e98 100755
--- a/t/t4053-diff-no-index.sh
+++ b/t/t4053-diff-no-index.sh
@@ -205,4 +205,9 @@  test_expect_success POSIXPERM,SYMLINKS 'diff --no-index normalizes: mode not lik
 	test_cmp expected actual
 '
 
+test_expect_success 'diff --no-index refuses to diff stdin and a directory' '
+	test_must_fail git diff --no-index -- - a </dev/null 2>err &&
+	grep "fatal: cannot compare stdin to a directory" err
+'
+
 test_done