From patchwork Wed Jul 5 19:49:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phillip Wood X-Patchwork-Id: 13302865 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DD0A9EB64DD for ; Wed, 5 Jul 2023 19:50:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234152AbjGETuO (ORCPT ); Wed, 5 Jul 2023 15:50:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53178 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233637AbjGETuK (ORCPT ); Wed, 5 Jul 2023 15:50:10 -0400 Received: from mail-lj1-x22a.google.com (mail-lj1-x22a.google.com [IPv6:2a00:1450:4864:20::22a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 54AE01730 for ; Wed, 5 Jul 2023 12:50:09 -0700 (PDT) Received: by mail-lj1-x22a.google.com with SMTP id 38308e7fff4ca-2b70404a5a0so3617131fa.2 for ; Wed, 05 Jul 2023 12:50:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1688586607; x=1691178607; h=content-transfer-encoding:mime-version:reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to; bh=xyZb0C9xsOze/kPweG6JBte8PhjiNbbjV6r/bHkkyW0=; b=bCmKg6RAX4XT4IGb7Q5gyB72tc08+BC3FA/4rkyb2uwRf2jGa+PIi+jil44d/3wTTc dTqT61Cj+jtb0SPk1EYThs063IXHO+PGF57C4wUFrgAcSenyDUsiSVI2CkjazeHAFd8o mB19OTQb6Uz/0YztRxg1YDg2cqvVrCNZ1w4PR6ivFp7PzkpSxrKpguuC/zogz4RMGUdd Zk8DjvORHCgpb+BMrcM7OarDp3iJNr3mKpERp1Id/V0EN0ZTl7orS7bffhqj/iaeBNGa RdpnMrf5MWp8DwO9dqk01YnRR8KWsFHDLeVaR0XmoZtrcsG+sps3eAC+zy+dErVsuGTe Bxmw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1688586607; x=1691178607; h=content-transfer-encoding:mime-version:reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=xyZb0C9xsOze/kPweG6JBte8PhjiNbbjV6r/bHkkyW0=; b=jJIEt6m8LALCJucr8uli3Fuyjym1W9wHLZB626fj2iLxucd5W4VpqPvF8sGmUtnWd5 qNd3aIg8rwB8lEbDc6gXQ56IJC0lmmXtNrAG4LZyZXP5rtZOtVH7Uc7o/GmCw+YG0vZb 7Soi+gftFPAevVWxO67L7gNClpGuhsTxzHxAnrwQToM2bcprcFYQaZ4oMVea08rpMAwq osT2NtdHFiJzP3n6wAerIH4ufw+sES2+DBVDJ0pNtq1bmhpv/W+EYqi8hY8xtE59RB/G JHIJSBA+g7yJHQuKv4PVgtUDI2T48vk6vHHmBvqsAIOyFhZlUjhCLyeiPAng/iZBtD3p OySA== X-Gm-Message-State: ABy/qLbAG0iF4wcz6lr8qdeJxLbQF1nBjEqU/bKW7rELqbZ6m6hZ5gMW UMfXIniZW0y1+Qo07sv2DjOZREI80Js= X-Google-Smtp-Source: APBJJlHm+qFUEG+gknW328xI2Z+Emy8afIhkJjzXfkbMviF4NyCeFSWUKnMhYiP0Y97Ubj3I3D8V4g== X-Received: by 2002:a2e:b0d6:0:b0:2b6:fc88:3ee7 with SMTP id g22-20020a2eb0d6000000b002b6fc883ee7mr3537883ljl.13.1688586607136; Wed, 05 Jul 2023 12:50:07 -0700 (PDT) Received: from localhost.localdomain ([90.242.235.211]) by smtp.gmail.com with ESMTPSA id bx1-20020a170906a1c100b00992665694f7sm10078341ejb.107.2023.07.05.12.50.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Jul 2023 12:50:06 -0700 (PDT) From: Phillip Wood To: git@vger.kernel.org Cc: Jeff King , Taylor Blau , "brian m. carlson" , Thomas Guyot-Sionnest , Junio C Hamano , Phillip Wood Subject: [PATCH v2 1/4] diff --no-index: refuse to compare stdin to a directory Date: Wed, 5 Jul 2023 20:49:27 +0100 Message-ID: <5e65a15223bc42293516308eb31ade5395609c55.1688586536.git.phillip.wood@dunelm.org.uk> X-Mailer: git-send-email 2.40.1.852.g0a1e0755a6 In-Reply-To: References: Reply-To: Phillip Wood MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Phillip Wood 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 --- diff-no-index.c | 12 +++++++----- t/t4053-diff-no-index.sh | 5 +++++ 2 files changed, 12 insertions(+), 5 deletions(-) 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 err && + grep "fatal: cannot compare stdin to a directory" err +' + test_done From patchwork Wed Jul 5 19:49:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phillip Wood X-Patchwork-Id: 13302868 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7CC65EB64DD for ; Wed, 5 Jul 2023 19:50:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234259AbjGETuQ (ORCPT ); Wed, 5 Jul 2023 15:50:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53190 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234062AbjGETuL (ORCPT ); Wed, 5 Jul 2023 15:50:11 -0400 Received: from mail-lj1-x232.google.com (mail-lj1-x232.google.com [IPv6:2a00:1450:4864:20::232]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 271B01737 for ; Wed, 5 Jul 2023 12:50:10 -0700 (PDT) Received: by mail-lj1-x232.google.com with SMTP id 38308e7fff4ca-2b6fbf0c0e2so27504631fa.2 for ; Wed, 05 Jul 2023 12:50:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1688586608; x=1691178608; h=content-transfer-encoding:mime-version:reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to; bh=s6vbsRn1QenTvSpUJatgMzNh/Aw/QxQzGqsDdX9W7Pc=; b=qdxh+oFclX/uCugYX5bTFwY4XF7OpcZFFCMgKnjbuOcogiiO5H0TOO6ObkczYJ+rWo +XL1xQLs/QsO+rtgw+/nJdb1ByAKyiW2YGBKeMhx12++Q34PFddbtt58aEXMb9ryYu8K ZQNdvjs+pLmGs8my/0ABH6ZYhhX3mKuzBgX7Gf6AboYraAA+4ley7TYZ9cRNH6vqGwy8 b+kQ2n73i5O4lTR966MK7Hk0wXcJpLgm3394X4kQEAUIC7uOiGTQKGGfMAZQdgD+/Z/C qEbBWoCnAYhyFFoD8QUbB+98f2tkjVG7WqPwYQcE5zpGuMX0UMQIVIR5FgtKJpf/OiLs gFBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1688586608; x=1691178608; h=content-transfer-encoding:mime-version:reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=s6vbsRn1QenTvSpUJatgMzNh/Aw/QxQzGqsDdX9W7Pc=; b=d5df54Vd/b0OmaGmXMPbrJhYTj4WDYXKeZa0EP3RdRUefj1H7fC6kxxjyf+sUIJowp CSQGoGzw10le8CKEwc2l58FsJNWmJmy4DsWIiuxQijDv63mwBbkLTF51Dwu9Q/XjebLe ZbtG5oGq26G0C5X2VsoeD/wM1QL5JXNv+lxMN/2XpGz+bugJcMTcvvXZ5TFfOM6F9X/Y L0l2UMkmtBuBuU33Rgc+vxX+y9kTOoklkcmfsbPMD1IqOzJ1hz1sEii5hWEO2FOQzQKC kW4zOB/UmPOJJLra+pO0lju59HfHReSyNFWhvpbvrehP05/onkngyGEYVAgMOAR8UBqW 16Tg== X-Gm-Message-State: ABy/qLbZDzSCA/G3UOHFnvd4FcPOCSse8KfAw+J40xbBO2F6pmMPatHH kfQNPFHkoFDr9A8KFZcyuZenvUbn9Ps= X-Google-Smtp-Source: APBJJlFsFqhoEgdfv7SLRtIqWtsVqlFiif4R5xNiQJ8DkauEMkXPEQIHJ+2cZL8SAubCWXs3FQzVBA== X-Received: by 2002:a2e:3a0f:0:b0:2b6:dec9:2813 with SMTP id h15-20020a2e3a0f000000b002b6dec92813mr9139991lja.29.1688586608208; Wed, 05 Jul 2023 12:50:08 -0700 (PDT) Received: from localhost.localdomain ([90.242.235.211]) by smtp.gmail.com with ESMTPSA id bx1-20020a170906a1c100b00992665694f7sm10078341ejb.107.2023.07.05.12.50.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Jul 2023 12:50:07 -0700 (PDT) From: Phillip Wood To: git@vger.kernel.org Cc: Jeff King , Taylor Blau , "brian m. carlson" , Thomas Guyot-Sionnest , Junio C Hamano , Phillip Wood Subject: [PATCH v2 2/4] diff --no-index: die on error reading stdin Date: Wed, 5 Jul 2023 20:49:28 +0100 Message-ID: X-Mailer: git-send-email 2.40.1.852.g0a1e0755a6 In-Reply-To: References: Reply-To: Phillip Wood MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Phillip Wood If there is an error when reading from stdin then "diff --no-index" prints an error message but continues to try and diff a file named "-" resulting in an error message that looks like error: error while reading from stdin: Invalid argument fatal: stat '-': No such file or directory assuming that no file named "-" exists. If such a file exists it prints the first error message and generates the diff from that file which is not what the user wanted. Instead just die() straight away if we cannot read from stdin. Signed-off-by: Phillip Wood --- diff-no-index.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/diff-no-index.c b/diff-no-index.c index 77462ac2a9..4470e0271d 100644 --- a/diff-no-index.c +++ b/diff-no-index.c @@ -60,20 +60,19 @@ static int get_mode(const char *path, int *mode) return 0; } -static int populate_from_stdin(struct diff_filespec *s) +static void populate_from_stdin(struct diff_filespec *s) { struct strbuf buf = STRBUF_INIT; size_t size = 0; if (strbuf_read(&buf, 0, 0) < 0) - return error_errno("error while reading from stdin"); + die_errno("error while reading from stdin"); s->should_munmap = 0; s->data = strbuf_detach(&buf, &size); s->size = size; s->should_free = 1; s->is_stdin = 1; - return 0; } static struct diff_filespec *noindex_filespec(const char *name, int mode) From patchwork Wed Jul 5 19:49:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phillip Wood X-Patchwork-Id: 13302866 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 22E5DC04A94 for ; Wed, 5 Jul 2023 19:50:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234315AbjGETuS (ORCPT ); Wed, 5 Jul 2023 15:50:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53224 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234023AbjGETuM (ORCPT ); Wed, 5 Jul 2023 15:50:12 -0400 Received: from mail-ej1-x62c.google.com (mail-ej1-x62c.google.com [IPv6:2a00:1450:4864:20::62c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C372D1981 for ; Wed, 5 Jul 2023 12:50:10 -0700 (PDT) Received: by mail-ej1-x62c.google.com with SMTP id a640c23a62f3a-99313a34b2dso423464666b.1 for ; Wed, 05 Jul 2023 12:50:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1688586609; x=1691178609; h=content-transfer-encoding:mime-version:reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to; bh=gOyQmT03UcfLFqZ5u2L9tJlQRdHPivGO2giZnWmPV2c=; b=Byo2AX5W0GceDV1xmx/efPvnlwcUZ5dphWOHa1WgQr2HVegv/avvBMuwCNi5hisPXk iCaIpM3htwyaZle7YpDaAAYA1wMPRa+9Q4Or6zWKG+eHup8BOAMtJCB/xFR8g+5TL0sF 4/UKCaagg7avdHTgVrEi+/bYn+z5xVmV8JEr05UryQt9wB91PBC1wpnjcZL8RZxvjwpa MxDlMvPfdlZo9cN8momJstx2V+Oebc4o05ligDB4K6DXmHoltcYfxy/dqZDnrqgiF/PB 32q42ql8U6yJtznAUQ4gEsdUSO6EHuGFSo42Ftm+2Z0O0xo+86oE5GjqJTgq3LF/bxqU W+qg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1688586609; x=1691178609; h=content-transfer-encoding:mime-version:reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=gOyQmT03UcfLFqZ5u2L9tJlQRdHPivGO2giZnWmPV2c=; b=K039m2SP4BSATPYTG+gmA3nfl//kERbO5oMwYvy96zJQebL8h8sTV+1W91D7EeYq+e fqZTXumPbsi3dNAUJVj9it36yZzlsa4U0X2JdGuOrVRMvCTKRduUxqmJfaNEHP1PXpf1 xFuxiuZz8/ujajt6tG+R7BxrtWCXNB2JoMK5FSmZoo5QNzIHe3+u5QvWYQLhD2Sh8Ygb 53l1gy1AuVdbLGcxvBGpMkc1ioUkjv1achDEPujvzwmQO6L/073P09F+tYDIDBO0GjDq 0KTgWl4y3UswMqwm4wOtl798Uqd2yqytSvIHojaCezT3T/qUlehWBFbMlMLBvhk/aC+f FDIA== X-Gm-Message-State: ABy/qLbr4p/9q9tNAJOLgHmYstFkBEaJLMeoWu9VJ6oV470kko1T+c4L +2aMflyyQrzVVIhJKsjW27VedCUy3ww= X-Google-Smtp-Source: APBJJlGyYd3LYAhfup6isRhj0OeLSNuxSR9S0RbhYnInnGVaEBBVBKKhNXfAmB33jIhCcfpPeqhpnQ== X-Received: by 2002:a17:906:24d:b0:973:e349:43c9 with SMTP id 13-20020a170906024d00b00973e34943c9mr13240436ejl.77.1688586609122; Wed, 05 Jul 2023 12:50:09 -0700 (PDT) Received: from localhost.localdomain ([90.242.235.211]) by smtp.gmail.com with ESMTPSA id bx1-20020a170906a1c100b00992665694f7sm10078341ejb.107.2023.07.05.12.50.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Jul 2023 12:50:08 -0700 (PDT) From: Phillip Wood To: git@vger.kernel.org Cc: Jeff King , Taylor Blau , "brian m. carlson" , Thomas Guyot-Sionnest , Junio C Hamano , Phillip Wood Subject: [PATCH v2 3/4] t4054: test diff --no-index with stdin Date: Wed, 5 Jul 2023 20:49:29 +0100 Message-ID: <1c7db4dbe26715912672630c1a5659591931cb2d.1688586536.git.phillip.wood@dunelm.org.uk> X-Mailer: git-send-email 2.40.1.852.g0a1e0755a6 In-Reply-To: References: Reply-To: Phillip Wood MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Phillip Wood "git diff --no-index" supports reading from stdin with the path "-". There is no test coverage for this so add a regression test before changing the code in the next commit. Signed-off-by: Phillip Wood --- t/t4053-diff-no-index.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh index 5bfb282e98..4870443609 100755 --- a/t/t4053-diff-no-index.sh +++ b/t/t4053-diff-no-index.sh @@ -205,6 +205,25 @@ test_expect_success POSIXPERM,SYMLINKS 'diff --no-index normalizes: mode not lik test_cmp expected actual ' +test_expect_success "diff --no-index treats '-' as stdin" ' + cat >expect <<-EOF && + diff --git a/- b/a/1 + index $ZERO_OID..$(git hash-object --stdin actual && + test_cmp expect actual && + + test_write_lines 1 | git diff --no-index -- a/1 - >actual && + test_must_be_empty actual +' + test_expect_success 'diff --no-index refuses to diff stdin and a directory' ' test_must_fail git diff --no-index -- - a err && grep "fatal: cannot compare stdin to a directory" err From patchwork Wed Jul 5 19:49:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phillip Wood X-Patchwork-Id: 13302867 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 71FAAEB64DA for ; Wed, 5 Jul 2023 19:50:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234001AbjGETuT (ORCPT ); Wed, 5 Jul 2023 15:50:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53192 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234049AbjGETuN (ORCPT ); Wed, 5 Jul 2023 15:50:13 -0400 Received: from mail-ej1-x636.google.com (mail-ej1-x636.google.com [IPv6:2a00:1450:4864:20::636]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DE3101985 for ; Wed, 5 Jul 2023 12:50:11 -0700 (PDT) Received: by mail-ej1-x636.google.com with SMTP id a640c23a62f3a-992acf67388so704251966b.1 for ; Wed, 05 Jul 2023 12:50:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1688586610; x=1691178610; h=content-transfer-encoding:mime-version:reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to; bh=YuiuopAFI+9CkSUb76FTvtN013GrgQYBYvhrAoKbW6k=; b=YZKYOHV4b7n+cMxHeavpuuwNNTtuvNqmiQILSHK0+UxY3E6iB1aAj5FGtiRMVA321k Go0z6v+BEfVGBfT/6cWG4304K4e3sFxNPIhmSm4HBASuTUsgfL2kN+Imk4D43mB1G0nN VzDk4m4jEw6YJAVQdEvS/Cpfgf0AApntyRl5fdyqtziW8DGluYMRZocSEjQhUTF23Lzb DcBpL+SCjfPFyezL+5hVmf1bATkChUS+9yRgXmOll2xjTkO9FwIv0UlVTSOlWyMYfOPN wa2Q6sobWdSxcW/OTxSE6l90aB2tbHpXDKZBxvMCZsLluGw6Mqh6QbFBKRs+tYBhI2gJ zayA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1688586610; x=1691178610; h=content-transfer-encoding:mime-version:reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=YuiuopAFI+9CkSUb76FTvtN013GrgQYBYvhrAoKbW6k=; b=VY9ga9NsxFPj3HIpeTHCsLDCITDy4Ltl/VWhHEbPXhlruWWWjesFF6KFLuPXfAaGbj LiUmGkRdnvoTSmMYdL3RyBQ3x2YY9XR4/WTpE+WKV9L9ZjaGkmSwGOMLCveXQJ/HXdHz UryltC0tyYG+AGPdA+UZDo3+h1y19voqZP2i25HbnGWOL1GqyvtOdoKDR9bOqGf126gA l6iIz5huvssfkV8WrOF9vOf3lbl8eR2gDV6T5fB3uYJqahRj3jqW7UVDg0IJdVBbU7zK kXPbQEp9fkf6nPIaJIZWma/9UGLT6CE0w69Puf/Hde0Ttwaz8a9Q1jzFtG58ILBibmyC rIzQ== X-Gm-Message-State: AC+VfDxpzZsnsAEO3mBURwNK1jA8aSrJsF5TMxEnZWsTH++Vw4l330BM qcTUvl5URsnGBDwu2A3rsCXrri9gZic= X-Google-Smtp-Source: APBJJlFF8XwMumraLJ8L96zmmpKxUsWF1zFMPAcM4WvQfeeSt1cpEzDzqidtwi3I2aCTFYSXoKZXOA== X-Received: by 2002:a17:906:bc88:b0:992:8892:141d with SMTP id lv8-20020a170906bc8800b009928892141dmr9798870ejb.22.1688586610057; Wed, 05 Jul 2023 12:50:10 -0700 (PDT) Received: from localhost.localdomain ([90.242.235.211]) by smtp.gmail.com with ESMTPSA id bx1-20020a170906a1c100b00992665694f7sm10078341ejb.107.2023.07.05.12.50.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Jul 2023 12:50:09 -0700 (PDT) From: Phillip Wood To: git@vger.kernel.org Cc: Jeff King , Taylor Blau , "brian m. carlson" , Thomas Guyot-Sionnest , Junio C Hamano , Phillip Wood Subject: [PATCH v2 4/4] diff --no-index: support reading from named pipes Date: Wed, 5 Jul 2023 20:49:30 +0100 Message-ID: <4e05a0be54f66f2b394642762832e426a545426c.1688586536.git.phillip.wood@dunelm.org.uk> X-Mailer: git-send-email 2.40.1.852.g0a1e0755a6 In-Reply-To: References: Reply-To: Phillip Wood MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Phillip Wood In some shells, such as bash and zsh, it's possible to use a command substitution to provide the output of a command as a file argument to another process, like so: diff -u <(printf "a\nb\n") <(printf "a\nc\n") However, this syntax does not produce useful results with "git diff --no-index". On macOS, the arguments to the command are named pipes under /dev/fd, and git diff doesn't know how to handle a named pipe. On Linux, the arguments are symlinks to pipes, so git diff "helpfully" diffs these symlinks, comparing their targets like "pipe:[1234]" and "pipe:[5678]". To address this "diff --no-index" is changed so that if a path given on the commandline is a named pipe or a symbolic link that resolves to a named pipe then we read the data to diff from that pipe. This is implemented by generalizing the code that already exists to handle reading from stdin when the user passes the path "-". If the user tries to compare a named pipe to a directory then we die as we do when trying to compare stdin to a directory. As process substitution is not support by POSIX this change is tested by using a pipe and a symbolic link to a pipe. Helped-by: Junio C Hamano Signed-off-by: Phillip Wood --- diff-no-index.c | 113 +++++++++++++++++++++++++++++---------- t/t4053-diff-no-index.sh | 40 ++++++++++++++ 2 files changed, 125 insertions(+), 28 deletions(-) diff --git a/diff-no-index.c b/diff-no-index.c index 4470e0271d..4771cf02aa 100644 --- a/diff-no-index.c +++ b/diff-no-index.c @@ -41,74 +41,119 @@ static int read_directory_contents(const char *path, struct string_list *list) */ static const char file_from_standard_input[] = "-"; -static int get_mode(const char *path, int *mode) +/* + * For paths given on the command-line we treat "-" as stdin and named + * pipes and symbolic links to named pipes specially. + */ +enum special { + SPECIAL_NONE, + SPECIAL_STDIN, + SPECIAL_PIPE, +}; + +static int get_mode(const char *path, int *mode, enum special *special) { struct stat st; - if (!path || !strcmp(path, "/dev/null")) + if (!path || !strcmp(path, "/dev/null")) { *mode = 0; #ifdef GIT_WINDOWS_NATIVE - else if (!strcasecmp(path, "nul")) + } else if (!strcasecmp(path, "nul")) { *mode = 0; #endif - else if (path == file_from_standard_input) + } else if (path == file_from_standard_input) { *mode = create_ce_mode(0666); - else if (lstat(path, &st)) + *special = SPECIAL_STDIN; + } else if (lstat(path, &st)) { return error("Could not access '%s'", path); - else + } else { *mode = st.st_mode; + } + /* + * For paths on the command-line treat named pipes and symbolic + * links that resolve to a named pipe specially. + */ + if (special && + (S_ISFIFO(*mode) || + (S_ISLNK(*mode) && !stat(path, &st) && S_ISFIFO(st.st_mode)))) { + *mode = create_ce_mode(0666); + *special = SPECIAL_PIPE; + } + return 0; } -static void populate_from_stdin(struct diff_filespec *s) +static void populate_common(struct diff_filespec *s, struct strbuf *buf) { - struct strbuf buf = STRBUF_INIT; size_t size = 0; - if (strbuf_read(&buf, 0, 0) < 0) - die_errno("error while reading from stdin"); - s->should_munmap = 0; - s->data = strbuf_detach(&buf, &size); + s->data = strbuf_detach(buf, &size); s->size = size; s->should_free = 1; s->is_stdin = 1; } -static struct diff_filespec *noindex_filespec(const char *name, int mode) +static void populate_from_pipe(struct diff_filespec *s) +{ + struct strbuf buf = STRBUF_INIT; + int fd = xopen(s->path, O_RDONLY); + + if (strbuf_read(&buf, fd, 0) < 0) + die_errno("error while reading from '%s'", s->path); + close(fd); + populate_common(s, &buf); +} + +static void populate_from_stdin(struct diff_filespec *s) +{ + struct strbuf buf = STRBUF_INIT; + + if (strbuf_read(&buf, 0, 0) < 0) + die_errno("error while reading from stdin"); + populate_common(s, &buf); +} + +static struct diff_filespec *noindex_filespec(const char *name, int mode, + enum special special) { struct diff_filespec *s; if (!name) name = "/dev/null"; s = alloc_filespec(name); fill_filespec(s, null_oid(), 0, mode); - if (name == file_from_standard_input) + if (special == SPECIAL_STDIN) populate_from_stdin(s); + else if (special == SPECIAL_PIPE) + populate_from_pipe(s); return s; } static int queue_diff(struct diff_options *o, - const char *name1, const char *name2) + const char *name1, const char *name2, int recursing) { int mode1 = 0, mode2 = 0; + enum special special1 = SPECIAL_NONE, special2 = SPECIAL_NONE; - if (get_mode(name1, &mode1) || get_mode(name2, &mode2)) + /* Paths can only be special if we're not recursing. */ + if (get_mode(name1, &mode1, recursing ? NULL : &special1) || + get_mode(name2, &mode2, recursing ? NULL : &special2)) return -1; if (mode1 && mode2 && S_ISDIR(mode1) != S_ISDIR(mode2)) { struct diff_filespec *d1, *d2; if (S_ISDIR(mode1)) { /* 2 is file that is created */ - d1 = noindex_filespec(NULL, 0); - d2 = noindex_filespec(name2, mode2); + d1 = noindex_filespec(NULL, 0, SPECIAL_NONE); + d2 = noindex_filespec(name2, mode2, special2); name2 = NULL; mode2 = 0; } else { /* 1 is file that is deleted */ - d1 = noindex_filespec(name1, mode1); - d2 = noindex_filespec(NULL, 0); + d1 = noindex_filespec(name1, mode1, special1); + d2 = noindex_filespec(NULL, 0, SPECIAL_NONE); name1 = NULL; mode1 = 0; } @@ -173,7 +218,7 @@ static int queue_diff(struct diff_options *o, n2 = buffer2.buf; } - ret = queue_diff(o, n1, n2); + ret = queue_diff(o, n1, n2, 1); } string_list_clear(&p1, 0); string_list_clear(&p2, 0); @@ -189,8 +234,8 @@ static int queue_diff(struct diff_options *o, SWAP(name1, name2); } - d1 = noindex_filespec(name1, mode1); - d2 = noindex_filespec(name2, mode2); + d1 = noindex_filespec(name1, mode1, special1); + d2 = noindex_filespec(name2, mode2, special2); diff_queue(&diff_queued_diff, d1, d2); return 0; } @@ -215,15 +260,27 @@ static void append_basename(struct strbuf *path, const char *dir, const char *fi */ static void fixup_paths(const char **path, struct strbuf *replacement) { - unsigned int isdir0, isdir1; - - isdir0 = path[0] != file_from_standard_input && is_directory(path[0]); - isdir1 = path[1] != file_from_standard_input && is_directory(path[1]); + struct stat st; + unsigned int isdir0 = 0, isdir1 = 0; + unsigned int ispipe0 = 0, ispipe1 = 0; + + if (path[0] != file_from_standard_input && !stat(path[0], &st)) { + isdir0 = S_ISDIR(st.st_mode); + ispipe0 = S_ISFIFO(st.st_mode); + } + + if (path[1] != file_from_standard_input && !stat(path[1], &st)) { + isdir1 = S_ISDIR(st.st_mode); + ispipe1 = S_ISFIFO(st.st_mode); + } if ((path[0] == file_from_standard_input && isdir1) || (isdir0 && path[1] == file_from_standard_input)) die(_("cannot compare stdin to a directory")); + if ((isdir0 && ispipe1) || (ispipe0 && isdir1)) + die(_("cannot compare a named pipe to a directory")); + if (isdir0 == isdir1) return; if (isdir0) { @@ -297,7 +354,7 @@ int diff_no_index(struct rev_info *revs, setup_diff_pager(&revs->diffopt); revs->diffopt.flags.exit_with_status = 1; - if (queue_diff(&revs->diffopt, paths[0], paths[1])) + if (queue_diff(&revs->diffopt, paths[0], paths[1], 0)) goto out; diff_set_mnemonic_prefix(&revs->diffopt, "1/", "2/"); diffcore_std(&revs->diffopt); diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh index 4870443609..a28b9ff243 100755 --- a/t/t4053-diff-no-index.sh +++ b/t/t4053-diff-no-index.sh @@ -229,4 +229,44 @@ test_expect_success 'diff --no-index refuses to diff stdin and a directory' ' grep "fatal: cannot compare stdin to a directory" err ' +test_expect_success PIPE 'diff --no-index refuses to diff a named pipe and a directory' ' + test_when_finished "rm -f pipe" && + mkfifo pipe && + { + (>pipe) & + } && + test_when_finished "kill $!" && + test_must_fail git diff --no-index -- pipe a 2>err && + grep "fatal: cannot compare a named pipe to a directory" err +' + +test_expect_success PIPE,SYMLINKS 'diff --no-index reads from pipes' ' + test_when_finished "rm -f old new new-link" && + mkfifo old && + mkfifo new && + ln -s new new-link && + { + (test_write_lines a b c >old) & + } && + test_when_finished "! kill $!" && + { + (test_write_lines a x c >new) & + } && + test_when_finished "! kill $!" && + + cat >expect <<-EOF && + diff --git a/old b/new-link + --- a/old + +++ b/new-link + @@ -1,3 +1,3 @@ + a + -b + +x + c + EOF + + test_expect_code 1 git diff --no-index old new-link >actual && + test_cmp expect actual +' + test_done