From patchwork Fri Aug 26 09:39:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Schindelin X-Patchwork-Id: 12955753 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 97DA0ECAAD2 for ; Fri, 26 Aug 2022 09:39:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1343984AbiHZJji (ORCPT ); Fri, 26 Aug 2022 05:39:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60282 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1343975AbiHZJjh (ORCPT ); Fri, 26 Aug 2022 05:39:37 -0400 Received: from mail-wr1-x435.google.com (mail-wr1-x435.google.com [IPv6:2a00:1450:4864:20::435]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C2B2A9DB41 for ; Fri, 26 Aug 2022 02:39:35 -0700 (PDT) Received: by mail-wr1-x435.google.com with SMTP id u5so1113360wrt.11 for ; Fri, 26 Aug 2022 02:39:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc; bh=R9n5jXs4FmjziGiQa7WHIy+y0b4GSV/osty3hWFDyCc=; b=SIvG56otYmjuYIU+Rldiqv2tfB7/3zo1GrjZGCbyxq/yeMGMXUjdIlV1RTypzED4vV ztv9F3HWbooknLd6pdd2ntactEvTMCPHavl1bEFGDmYEInYFNr74mlCaPPW+DjCNq7gy BPnYMIfhaM2nPaqeiCBMsWUL1szdQlaYoFhTM8lQPRI/xpuC+mU81SZhilbyUN9q+Wfq Gy8QhMIGVBwI8GhRdBOXKqdYpVT4f5cLoPlYg9yH5nT01uBUBIYbW//2/0V4ZJVEZ/c/ S3rUBNjWqsZ6qOUS4uQflDOtNaZQjlYKvYvRYdiNtjdrBcMIxDjZksDZ1iWBhidz/rYk aFig== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc; bh=R9n5jXs4FmjziGiQa7WHIy+y0b4GSV/osty3hWFDyCc=; b=GDzm3bUELlPSENeBTrbqStxw/kRH7UvQvGcCPWcLgkad5mEzjz/6PKmPucZotbCOaK 1ApMcDZpX8Sxh9MCDkJ+c4+VuKX7wVYV+ZnFvm2Eb0FHQfkrRvhh2JHdGH4ZQAxYigcM vl+siEOcFFXVqB1TccIcAEafkuZumK/llDg82mTus1D00mn+veXuJrhPw3HRHHKqGmFT UxIWAJWinVRECTsZioOYElpJI7b8/zJ2RAQ3svH57w0Mh7zdHE7KqVYiJ9PBqf6fkbIV rwXHG+R/dA94p4Wk9aEj45rJv/r6nfbTP4eaRbikemC4hY8muyeJ0k8W+vQJtB5rl27c 6Brg== X-Gm-Message-State: ACgBeo39vhRvl8zwsQFbPFxSski5KQ9uiQyuIrSMVIVt1QIJQiS7WTUc P8RvHj6xfyFEK9y4pPAAUZOx2t82iPU= X-Google-Smtp-Source: AA6agR7kIJJGwjKN7S6qTF1vuACSUn0QPUsqz6c1kusk8cNp+GsaxIoseKcFy2HHfP6Fe91HMaJuuQ== X-Received: by 2002:a5d:6da9:0:b0:225:59e2:ee40 with SMTP id u9-20020a5d6da9000000b0022559e2ee40mr4269381wrs.540.1661506774051; Fri, 26 Aug 2022 02:39:34 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id e16-20020a05600c219000b003a5537bb2besm1834294wme.25.2022.08.26.02.39.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 26 Aug 2022 02:39:33 -0700 (PDT) Message-Id: <150f29a1c48917577ccaa93c0d4548c871adc1f6.1661506770.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Fri, 26 Aug 2022 09:39:28 +0000 Subject: [PATCH v2 1/3] range-diff: reorder argument handling Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Johannes Schindelin , Johannes Schindelin Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Johannes Schindelin From: Johannes Schindelin In d9c66f0b5bf (range-diff: first rudimentary implementation, 2018-08-13), we introduced the argument handling of the `range-diff` command, special-casing three different stanzas based on the argument count. The somewhat unorthodox order (first handling the case of 2 arguments, then 3, then 1) was chosen for clarity: the natural argument number is 2 because that is how many revision ranges are used internally. The code to handle three arguments is relatively trivial, so it was added next. And finally, the code to ungarble a single symmetric range into two separate ones was added, because it was the most complicated (the most inelegant part being about interpreting empty sides of the symmetric range as `HEAD`). In preparation for allowing pathspecs in `git range-diff` invocations, where we no longer have the luxury of using the number of arguments to disambiguate between these three different ways to specify the commit ranges, we need to order these cases by argument count, in descending order. This patch is best viewed with `--color-moved`. Signed-off-by: Johannes Schindelin --- builtin/range-diff.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/builtin/range-diff.c b/builtin/range-diff.c index 50318849d65..f8d3869d357 100644 --- a/builtin/range-diff.c +++ b/builtin/range-diff.c @@ -55,7 +55,10 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix) if (!simple_color) diffopt.use_color = 1; - if (argc == 2) { + if (argc == 3) { + strbuf_addf(&range1, "%s..%s", argv[0], argv[1]); + strbuf_addf(&range2, "%s..%s", argv[0], argv[2]); + } else if (argc == 2) { if (!is_range_diff_range(argv[0])) die(_("not a commit range: '%s'"), argv[0]); strbuf_addstr(&range1, argv[0]); @@ -63,9 +66,6 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix) if (!is_range_diff_range(argv[1])) die(_("not a commit range: '%s'"), argv[1]); strbuf_addstr(&range2, argv[1]); - } else if (argc == 3) { - strbuf_addf(&range1, "%s..%s", argv[0], argv[1]); - strbuf_addf(&range2, "%s..%s", argv[0], argv[2]); } else if (argc == 1) { const char *b = strstr(argv[0], "..."), *a = argv[0]; int a_len; From patchwork Fri Aug 26 09:39:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Schindelin X-Patchwork-Id: 12955754 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 631E0ECAAD8 for ; Fri, 26 Aug 2022 09:39:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1343989AbiHZJjj (ORCPT ); Fri, 26 Aug 2022 05:39:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60290 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1343852AbiHZJjh (ORCPT ); Fri, 26 Aug 2022 05:39:37 -0400 Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D081DAE216 for ; Fri, 26 Aug 2022 02:39:36 -0700 (PDT) Received: by mail-wr1-x42e.google.com with SMTP id n17so1136561wrm.4 for ; Fri, 26 Aug 2022 02:39:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc; bh=cozaAwc+epvp4IegY/IBfVoSuI833gg9OLEeBehc8B4=; b=YVBCwwv9fqU7V+bCVTNBkyn2y5OkxVONC01/q6+ssg78kOsafErILNtvQcSvxv1hbY 3BeOEC1TgAT1gHQHCObatZMbwuZR0Dr9EKwZDKkvkp+oONUGEEAbnKv6IHZcSI3+fV4/ 5g2SwLrW8cjZmocVdJKVdKWlgM19z0aChau9g71YcOaEs+gVHC6eB2vijlE5J0aP8NFH LgDctFStPHo/8iSvAIqnExcsQAgB4eN6oGLAqFY27YZSvfn6yqlFpHHSuhaxnvPytDZY vKI/LlQC8LEUkh1JoVUk1IlSXbodqZXcvlACqpYneDOsbiy8bSQij/CAExNwuDH3m+Qi FdsQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc; bh=cozaAwc+epvp4IegY/IBfVoSuI833gg9OLEeBehc8B4=; b=NcP51Zwpn87aXuW1V7qNlirmIqjYVLN1X7vBUiSNcjFYmgMkM/jEtZy4GmLCVhffJM 9Jp6RKwHjhHZJ4ZJANRx2EHoYIUX/rhxSul99Q0TEQaucSjxd6Yxikvdde7aVxFWBpIN MXQoChQhMvPyct4p+q/5q5UpX0Xv8wg1Zp+jFZLojHvOFxY5/aqsM674X431AUaBZU7R G6HW+KsvyqyEGr0mpjYzMd/loylpDdhFimmJAZ12h/HnJCFMwQ/N08LEJAERTH5NnAdw wgzrF41DCoRF4u+Y865vvwccSHiAU647zyVpgi4+BNhWxPBk94WJ1MyMsRuWzJafyKKS 933w== X-Gm-Message-State: ACgBeo2MoL2kfDj3CvOGHMs5sUyFDqQUyV1JFD05GvjmvsdLSP0RdNDj 1Mle//xD0kuC5pxr7dj0983lJgQKEJw= X-Google-Smtp-Source: AA6agR6m1IAa1a3JLdwtbPdcoStrhHI5dvgE61KvKLAMScaPlo2dNITz5F7uITPyAc6ObNF526Adjw== X-Received: by 2002:adf:e101:0:b0:225:a31:854b with SMTP id t1-20020adfe101000000b002250a31854bmr4288420wrz.143.1661506775142; Fri, 26 Aug 2022 02:39:35 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id p11-20020adff20b000000b002257f1a227dsm1439999wro.46.2022.08.26.02.39.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 26 Aug 2022 02:39:34 -0700 (PDT) Message-Id: <4cd7f09557c7d0a4802b07d1e8440015e0a50524.1661506770.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Fri, 26 Aug 2022 09:39:29 +0000 Subject: [PATCH v2 2/3] range-diff: consistently validate the arguments Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Johannes Schindelin , Johannes Schindelin Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Johannes Schindelin From: Johannes Schindelin This patch lets `range-diff` validate the arguments not only when invoked with one or two arguments, but also in the code path where three arguments are handled. While at it, we now use `usage_msg_opt*()` consistently. Signed-off-by: Johannes Schindelin --- builtin/range-diff.c | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/builtin/range-diff.c b/builtin/range-diff.c index f8d3869d357..71319ed1d84 100644 --- a/builtin/range-diff.c +++ b/builtin/range-diff.c @@ -40,6 +40,7 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix) struct option *options; int res = 0; struct strbuf range1 = STRBUF_INIT, range2 = STRBUF_INIT; + struct object_id oid; git_config(git_diff_ui_config, NULL); @@ -56,24 +57,41 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix) diffopt.use_color = 1; if (argc == 3) { + if (get_oid_committish(argv[0], &oid)) + usage_msg_optf(_("not a revision: '%s'"), + builtin_range_diff_usage, options, + argv[0]); + else if (get_oid_committish(argv[1], &oid)) + usage_msg_optf(_("not a revision: '%s'"), + builtin_range_diff_usage, options, + argv[1]); + else if (get_oid_committish(argv[2], &oid)) + usage_msg_optf(_("not a revision: '%s'"), + builtin_range_diff_usage, options, + argv[2]); + strbuf_addf(&range1, "%s..%s", argv[0], argv[1]); strbuf_addf(&range2, "%s..%s", argv[0], argv[2]); } else if (argc == 2) { if (!is_range_diff_range(argv[0])) - die(_("not a commit range: '%s'"), argv[0]); - strbuf_addstr(&range1, argv[0]); + usage_msg_optf(_("not a commit range: '%s'"), + builtin_range_diff_usage, options, + argv[0]); + else if (!is_range_diff_range(argv[1])) + usage_msg_optf(_("not a commit range: '%s'"), + builtin_range_diff_usage, options, + argv[1]); - if (!is_range_diff_range(argv[1])) - die(_("not a commit range: '%s'"), argv[1]); + strbuf_addstr(&range1, argv[0]); strbuf_addstr(&range2, argv[1]); } else if (argc == 1) { const char *b = strstr(argv[0], "..."), *a = argv[0]; int a_len; - if (!b) { - error(_("single arg format must be symmetric range")); - usage_with_options(builtin_range_diff_usage, options); - } + if (!b) + usage_msg_optf(_("not a symmetric range: '%s'"), + builtin_range_diff_usage, options, + argv[0]); a_len = (int)(b - a); if (!a_len) { @@ -85,10 +103,9 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix) b = "HEAD"; strbuf_addf(&range1, "%s..%.*s", b, a_len, a); strbuf_addf(&range2, "%.*s..%s", a_len, a, b); - } else { - error(_("need two commit ranges")); - usage_with_options(builtin_range_diff_usage, options); - } + } else + usage_msg_opt(_("need two commit ranges"), + builtin_range_diff_usage, options); FREE_AND_NULL(options); range_diff_opts.dual_color = simple_color < 1; From patchwork Fri Aug 26 09:39:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Schindelin X-Patchwork-Id: 12955755 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 20BBCECAAD2 for ; Fri, 26 Aug 2022 09:39:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1343992AbiHZJjq (ORCPT ); Fri, 26 Aug 2022 05:39:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60394 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1343987AbiHZJjl (ORCPT ); Fri, 26 Aug 2022 05:39:41 -0400 Received: from mail-wm1-x32a.google.com (mail-wm1-x32a.google.com [IPv6:2a00:1450:4864:20::32a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E8D85D1E0B for ; Fri, 26 Aug 2022 02:39:38 -0700 (PDT) Received: by mail-wm1-x32a.google.com with SMTP id m10-20020a05600c3b0a00b003a603fc3f81so533683wms.0 for ; Fri, 26 Aug 2022 02:39:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:from:to:cc; bh=ZmVdsax1U7DugzWwlXsVvugjEwC680jK/Qnbw4xSEr4=; b=ZahBUP+qBVdFl28CVWdthAF4TTE1/it3jx3ZND3434rF6Hv+H+WVh2IY/+LdZptesw 09lBxO/VboeLDEvj8TXtYeCc1LH7yITYW/EwGogxx6G9Po//lBL/VOyF18Bz8FLI15/C jQSO+oz7j3XhNuoJKKiaAHwVIEf7nLxFZuV9QYydaKj6h85c8O5nCdsoZR/lx/V/Q07N XSvWCBCqhRTwZPGlcjnlJVl4NqKRaELyRWWuR7vxnpR43gnYQJJlZzV6BTi3agY/Y1Ql x1ft9fyo/DixmUTX7+89gySdlgHfxta/yo9d5YxTx1W7M4L2uaMEN7O050P1O1wgY01+ AeoA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date:from :references:in-reply-to:message-id:x-gm-message-state:from:to:cc; bh=ZmVdsax1U7DugzWwlXsVvugjEwC680jK/Qnbw4xSEr4=; b=wA5EH0m1Z6XwrflRTPhrcrWV2d9Y/0spPtXSQlNUyq0FM9ySKpugXob/ZclegUgvHY Qm9a3Kz3HkT1kBsn6MtTiU1V+ZbqRvKoFKQiPMtWwTXCTG9uv1TUn9kHsrvMf2J7y5JE UmsBWYq+VEeGE4YS3kOlh+WpbV5Nw34SywByml6dQfTCyOuhbDlGv7deivu6Kn3oi55Y a2qC+UUOU4bImzFU58+LJEMZXzmaWUROsVpp76AXJe56kjdyKkAAMo2RvRp5jJhm5gEf 5IE3DeFFj+kQoYtMDZkKm3cl1B3APuq0ZfyvAK18+nv+c+F30x5YDhbzNk8hOEUfGGYB uMMw== X-Gm-Message-State: ACgBeo1E4Aw4016mZG0ZTd48nlkOth1+M/KH0OYxMKR+DUmgvRzXN4AQ YvVaFnr93RwU+aokaJnStTC4Ur6B2R8= X-Google-Smtp-Source: AA6agR7iQ+BrGEVuQJ29b69MHMIInct365mLwUVLJA5j44N63mI79pc++L+LKUwsQfb12rRywWZWQA== X-Received: by 2002:a05:600c:4a09:b0:3a6:9a22:3979 with SMTP id c9-20020a05600c4a0900b003a69a223979mr4230672wmp.57.1661506776474; Fri, 26 Aug 2022 02:39:36 -0700 (PDT) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id t63-20020a1c4642000000b003a673055e68sm8973807wma.0.2022.08.26.02.39.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 26 Aug 2022 02:39:35 -0700 (PDT) Message-Id: In-Reply-To: References: Date: Fri, 26 Aug 2022 09:39:30 +0000 Subject: [PATCH v2 3/3] range-diff: optionally accept pathspecs Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Johannes Schindelin , Johannes Schindelin Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Johannes Schindelin From: Johannes Schindelin The `git range-diff` command can be quite expensive, which is not a surprise given that the underlying algorithm to match up pairs of commits between the provided two commit ranges has a cubic runtime. Therefore it makes sense to restrict the commit ranges as much as possible, to reduce the amount of input to that O(N^3) algorithm. In chatty repositories with wide trees, this is not necessarily possible merely by choosing commit ranges wisely. Let's give users another option to restrict the commit ranges: by providing a pathspec. That helps in repositories with wide trees because it is likely that the user has a good idea which subset of the tree they are actually interested in. Example: git range-diff upstream/main upstream/seen HEAD -- range-diff.c This shows commits that are either in the local branch or in `seen`, but not in `main`, skipping all commits that do not touch `range-diff.c`. Note: Since we piggy-back the pathspecs onto the `other_arg` mechanism that was introduced to be able to pass through the `--notes` option to the revision machinery, we must now ensure that the `other_arg` array is appended at the end (the revision range must come before the pathspecs, if any). Signed-off-by: Johannes Schindelin --- Documentation/git-range-diff.txt | 4 ++ builtin/range-diff.c | 66 ++++++++++++++++++++++++-------- range-diff.c | 2 +- t/t3206-range-diff.sh | 13 ++++++- 4 files changed, 68 insertions(+), 17 deletions(-) diff --git a/Documentation/git-range-diff.txt b/Documentation/git-range-diff.txt index fe350d7f405..0b393715d70 100644 --- a/Documentation/git-range-diff.txt +++ b/Documentation/git-range-diff.txt @@ -12,6 +12,7 @@ SYNOPSIS [--no-dual-color] [--creation-factor=] [--left-only | --right-only] ( | ... | ) + [[--] ...] DESCRIPTION ----------- @@ -19,6 +20,9 @@ DESCRIPTION This command shows the differences between two versions of a patch series, or more generally, two commit ranges (ignoring merge commits). +In the presence of `` arguments, these commit ranges are limited +accordingly. + To that end, it first finds pairs of commits from both commit ranges that correspond with each other. Two commits are said to correspond when the diff between their patches (i.e. the author information, the commit diff --git a/builtin/range-diff.c b/builtin/range-diff.c index 71319ed1d84..e2a74efb42a 100644 --- a/builtin/range-diff.c +++ b/builtin/range-diff.c @@ -38,9 +38,10 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix) OPT_END() }; struct option *options; - int res = 0; + int i, dash_dash = -1, res = 0; struct strbuf range1 = STRBUF_INIT, range2 = STRBUF_INIT; struct object_id oid; + const char *three_dots = NULL; git_config(git_diff_ui_config, NULL); @@ -48,7 +49,7 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix) options = parse_options_concat(range_diff_options, diffopt.parseopts); argc = parse_options(argc, argv, prefix, options, - builtin_range_diff_usage, 0); + builtin_range_diff_usage, PARSE_OPT_KEEP_DASHDASH); diff_setup_done(&diffopt); @@ -56,8 +57,20 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix) if (!simple_color) diffopt.use_color = 1; - if (argc == 3) { - if (get_oid_committish(argv[0], &oid)) + for (i = 0; i < argc; i++) + if (!strcmp(argv[i], "--")) { + dash_dash = i; + break; + } + + if (dash_dash == 3 || + (dash_dash < 0 && argc > 2 && + !get_oid_committish(argv[0], &oid) && + !get_oid_committish(argv[1], &oid) && + !get_oid_committish(argv[2], &oid))) { + if (dash_dash < 0) + ; /* already validated arguments */ + else if (get_oid_committish(argv[0], &oid)) usage_msg_optf(_("not a revision: '%s'"), builtin_range_diff_usage, options, argv[0]); @@ -72,8 +85,16 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix) strbuf_addf(&range1, "%s..%s", argv[0], argv[1]); strbuf_addf(&range2, "%s..%s", argv[0], argv[2]); - } else if (argc == 2) { - if (!is_range_diff_range(argv[0])) + + strvec_pushv(&other_arg, argv + + (dash_dash < 0 ? 3 : dash_dash)); + } else if (dash_dash == 2 || + (dash_dash < 0 && argc > 1 && + is_range_diff_range(argv[0]) && + is_range_diff_range(argv[1]))) { + if (dash_dash < 0) + ; /* already validated arguments */ + else if (!is_range_diff_range(argv[0])) usage_msg_optf(_("not a commit range: '%s'"), builtin_range_diff_usage, options, argv[0]); @@ -84,25 +105,40 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix) strbuf_addstr(&range1, argv[0]); strbuf_addstr(&range2, argv[1]); - } else if (argc == 1) { - const char *b = strstr(argv[0], "..."), *a = argv[0]; + + strvec_pushv(&other_arg, argv + + (dash_dash < 0 ? 2 : dash_dash)); + } else if (dash_dash == 1 || + (dash_dash < 0 && argc > 0 && + (three_dots = strstr(argv[0], "...")))) { + const char *a, *b; int a_len; - if (!b) + if (dash_dash < 0) + ; /* already validated arguments */ + else if (!(three_dots = strstr(argv[0], "..."))) usage_msg_optf(_("not a symmetric range: '%s'"), - builtin_range_diff_usage, options, - argv[0]); + builtin_range_diff_usage, options, + argv[0]); - a_len = (int)(b - a); - if (!a_len) { + if (three_dots == argv[0]) { a = "HEAD"; a_len = strlen(a); + } else { + a = argv[0]; + a_len = (int)(three_dots - a); } - b += 3; - if (!*b) + + if (three_dots[3]) + b = three_dots + 3; + else b = "HEAD"; + strbuf_addf(&range1, "%s..%.*s", b, a_len, a); strbuf_addf(&range2, "%.*s..%s", a_len, a, b); + + strvec_pushv(&other_arg, argv + + (dash_dash < 0 ? 1 : dash_dash)); } else usage_msg_opt(_("need two commit ranges"), builtin_range_diff_usage, options); diff --git a/range-diff.c b/range-diff.c index f63b3ffc200..124dd678c38 100644 --- a/range-diff.c +++ b/range-diff.c @@ -57,9 +57,9 @@ static int read_patches(const char *range, struct string_list *list, "--pretty=medium", "--notes", NULL); + strvec_push(&cp.args, range); if (other_arg) strvec_pushv(&cp.args, other_arg->v); - strvec_push(&cp.args, range); cp.out = -1; cp.no_stdin = 1; cp.git_cmd = 1; diff --git a/t/t3206-range-diff.sh b/t/t3206-range-diff.sh index d12e4e4cc6c..459beaf7d9c 100755 --- a/t/t3206-range-diff.sh +++ b/t/t3206-range-diff.sh @@ -162,7 +162,7 @@ test_expect_success 'A^! and A^- (unmodified)' ' ' test_expect_success 'A^{/..} is not mistaken for a range' ' - test_must_fail git range-diff topic^.. topic^{/..} 2>error && + test_must_fail git range-diff topic^.. topic^{/..} -- 2>error && test_i18ngrep "not a commit range" error ' @@ -772,6 +772,17 @@ test_expect_success '--left-only/--right-only' ' test_cmp expect actual ' +test_expect_success 'ranges with pathspecs' ' + git range-diff topic...mode-only-change -- other-file >actual && + test_line_count = 2 actual && + topic_oid=$(git rev-parse --short topic) && + mode_change_oid=$(git rev-parse --short mode-only-change^) && + file_change_oid=$(git rev-parse --short mode-only-change) && + grep "$mode_change_oid" actual && + ! grep "$file_change_oid" actual && + ! grep "$topic_oid" actual +' + test_expect_success 'submodule changes are shown irrespective of diff.submodule' ' git init sub-repo && test_commit -C sub-repo sub-first &&