Re: [PATCH 2/2] Allow passing pipes for input pipes to diff --no-index
- From
brian m. carlson <sandals@crustytoothpaste.net>
- Date
- Sep 18, 2020, 21:56 UTC
- Message-ID
- <20200918215623.GE67496@camp.crustytoothpaste.net>
- In-Reply-To
- <20200918113256.8699-3-tguyot@gmail.com>
On 2020-09-18 at 11:32:56, Thomas Guyot-Sionnest wrote:
Show 30 quoted lines
> diff --git a/diff-no-index.c b/diff-no-index.c
> index 7814eabfe0..779c686d23 100644
> --- a/diff-no-index.c
> +++ b/diff-no-index.c
> @@ -41,6 +41,33 @@ static int read_directory_contents(const char *path, struct string_list *list)
> */
> static const char file_from_standard_input[] = "-";
>
> +/* Check that file is - (STDIN) or unnamed pipe - explicitly
> + * avoid on-disk named pipes which could block
> + */
> +static int ispipe(const char *name)
> +{
> + struct stat st;
> +
> + if (name == file_from_standard_input)
> + return 1; /* STDIN */
> +
> + if (!lstat(name, &st)) {
> + if (S_ISLNK(st.st_mode)) {
> + /* symlink - read it and check it doesn't exists
> + * as a file yet link to a pipe */
> + struct strbuf sb = STRBUF_INIT;
> + strbuf_realpath(&sb, name, 0);
> + /* We're abusing strbuf_realpath here, it may append
> + * pipe:[NNNNNNNNN] to an abs path */
> + if (!stat(sb.buf, &st))
> + return 0; /* link target exists , not pipe */
> + if (!stat(name, &st))
> + return S_ISFIFO(st.st_mode);This makes a lot of assumptions about the implementation which are specific to Linux, namely that an anonymous pipe will be a symlink to a FIFO. That's not the case on macOS, where the /dev/fd entries are actually named pipes themselves.
Granted, in that case, Git just chokes and fails instead of diffing the symlink values, but I suspect you'll want this to work on macOS as well. I don't use macOS that often, but I would appreciate it if it worked when I did, and I'm sure others will as well.
I think we can probably get away with just doing a regular stat and seeing if S_ISFIFO is true, which is both simpler and cheaper.
Show 18 quoted lines
> diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh > index 0168946b63..e49f773515 100755 > --- a/t/t4053-diff-no-index.sh > +++ b/t/t4053-diff-no-index.sh > @@ -144,4 +144,193 @@ test_expect_success 'diff --no-index allows external diff' ' > test_cmp expect actual > ' > > +test_expect_success 'diff --no-index can diff piped subshells' ' > + echo 1 >non/git/c && > + test_expect_code 0 git diff --no-index non/git/b <(cat non/git/c) && > + test_expect_code 0 git diff --no-index <(cat non/git/b) non/git/c && > + test_expect_code 0 git diff --no-index <(cat non/git/b) <(cat non/git/c) && > + test_expect_code 0 cat non/git/b | git diff --no-index - non/git/c && > + test_expect_code 0 cat non/git/c | git diff --no-index non/git/b - && > + test_expect_code 0 cat non/git/b | git diff --no-index - <(cat non/git/c) && > + test_expect_code 0 cat non/git/c | git diff --no-index <(cat non/git/b) - > +'
As mentioned by others, this requires non-POSIX syntax. /bin/sh on my Debian system is dash, which doesn't support this. You can either use a prerequisite, or just test by piping from standard input and assume that Git can handle the rest. I would recommend at least adding some POSIX testcases that use only a pipe from standard input to avoid regressing this behavior on Debian and Ubuntu.
-- brian m. carlson: Houston, Texas, US