git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] Allow passing pathspecs to git range-diff
@ 2022-08-23 12:35 Johannes Schindelin via GitGitGadget
  2022-08-23 12:35 ` [PATCH 1/2] range-diff: reorder argument handling Johannes Schindelin via GitGitGadget
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Johannes Schindelin via GitGitGadget @ 2022-08-23 12:35 UTC (permalink / raw)
  To: git; +Cc: Johannes Schindelin

I just had the need to find out upstream commits corresponding to a handful
of backported commits, and most importantly, identify upstream commits
touching a given file that had not yet been backported.

This new mode helped me identify them.

Johannes Schindelin (2):
  range-diff: reorder argument handling
  range-diff: optionally accept a pathspec

 Documentation/git-range-diff.txt |  4 +++
 builtin/range-diff.c             | 54 ++++++++++++++++++++++++--------
 range-diff.c                     |  2 +-
 t/t3206-range-diff.sh            | 11 +++++++
 4 files changed, 57 insertions(+), 14 deletions(-)


base-commit: 795ea8776befc95ea2becd8020c7a284677b4161
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1335%2Fdscho%2Frange-diff-with-pathspec-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1335/dscho/range-diff-with-pathspec-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/1335
-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/2] range-diff: reorder argument handling
  2022-08-23 12:35 [PATCH 0/2] Allow passing pathspecs to git range-diff Johannes Schindelin via GitGitGadget
@ 2022-08-23 12:35 ` Johannes Schindelin via GitGitGadget
  2022-08-23 12:35 ` [PATCH 2/2] range-diff: optionally accept a pathspec Johannes Schindelin via GitGitGadget
  2022-08-26  9:39 ` [PATCH v2 0/3] Allow passing pathspecs to git range-diff Johannes Schindelin via GitGitGadget
  2 siblings, 0 replies; 10+ messages in thread
From: Johannes Schindelin via GitGitGadget @ 2022-08-23 12:35 UTC (permalink / raw)
  To: git; +Cc: Johannes Schindelin, Johannes Schindelin

From: Johannes Schindelin <johannes.schindelin@gmx.de>

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 ascending
order.

This patch is best viewed with `--color-moved`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 builtin/range-diff.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/builtin/range-diff.c b/builtin/range-diff.c
index 50318849d65..c8ffcd35aea 100644
--- a/builtin/range-diff.c
+++ b/builtin/range-diff.c
@@ -55,18 +55,7 @@ int cmd_range_diff(int argc, const char **argv, const char *prefix)
 	if (!simple_color)
 		diffopt.use_color = 1;
 
-	if (argc == 2) {
-		if (!is_range_diff_range(argv[0]))
-			die(_("not a commit range: '%s'"), argv[0]);
-		strbuf_addstr(&range1, argv[0]);
-
-		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) {
+	if (argc == 1) {
 		const char *b = strstr(argv[0], "..."), *a = argv[0];
 		int a_len;
 
@@ -85,6 +74,17 @@ 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 if (argc == 2) {
+		if (!is_range_diff_range(argv[0]))
+			die(_("not a commit range: '%s'"), argv[0]);
+		strbuf_addstr(&range1, argv[0]);
+
+		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 {
 		error(_("need two commit ranges"));
 		usage_with_options(builtin_range_diff_usage, options);
-- 
gitgitgadget


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/2] range-diff: optionally accept a pathspec
  2022-08-23 12:35 [PATCH 0/2] Allow passing pathspecs to git range-diff Johannes Schindelin via GitGitGadget
  2022-08-23 12:35 ` [PATCH 1/2] range-diff: reorder argument handling Johannes Schindelin via GitGitGadget
@ 2022-08-23 12:35 ` Johannes Schindelin via GitGitGadget
  2022-08-24 21:00   ` Junio C Hamano
  2022-08-26  9:39 ` [PATCH v2 0/3] Allow passing pathspecs to git range-diff Johannes Schindelin via GitGitGadget
  2 siblings, 1 reply; 10+ messages in thread
From: Johannes Schindelin via GitGitGadget @ 2022-08-23 12:35 UTC (permalink / raw)
  To: git; +Cc: Johannes Schindelin, Johannes Schindelin

From: Johannes Schindelin <johannes.schindelin@gmx.de>

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 <johannes.schindelin@gmx.de>
---
 Documentation/git-range-diff.txt |  4 ++++
 builtin/range-diff.c             | 30 +++++++++++++++++++++++++++++-
 range-diff.c                     |  2 +-
 t/t3206-range-diff.sh            | 11 +++++++++++
 4 files changed, 45 insertions(+), 2 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=<factor>]
 	[--left-only | --right-only]
 	( <range1> <range2> | <rev1>...<rev2> | <base> <rev1> <rev2> )
+	[[--] <path>...]
 
 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 `<path>` 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 c8ffcd35aea..9ae95b9c950 100644
--- a/builtin/range-diff.c
+++ b/builtin/range-diff.c
@@ -40,6 +40,8 @@ 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;
+	const char *p;
 
 	git_config(git_diff_ui_config, NULL);
 
@@ -47,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);
 
@@ -74,6 +76,20 @@ 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 if (argc > 1 && (p = strstr(argv[0], "..."))) {
+		const char *a = argv[0];
+		int a_len = (int)(p - a);
+
+		if (!a_len) {
+			a = "HEAD";
+			a_len = strlen(a);
+		}
+		p += 3;
+		if (!*p)
+			p = "HEAD";
+		strbuf_addf(&range1, "%s..%.*s", p, a_len, a);
+		strbuf_addf(&range2, "%.*s..%s", a_len, a, p);
+		strvec_pushv(&other_arg, argv + 1);
 	} else if (argc == 2) {
 		if (!is_range_diff_range(argv[0]))
 			die(_("not a commit range: '%s'"), argv[0]);
@@ -82,9 +98,21 @@ 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 > 2 &&
+	    is_range_diff_range(argv[0]) && is_range_diff_range(argv[1])) {
+		strbuf_addstr(&range1, argv[0]);
+		strbuf_addstr(&range2, argv[1]);
+		strvec_pushv(&other_arg, argv + 2);
 	} 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 > 3 &&
+		   get_oid_committish(argv[0], &oid) &&
+		   get_oid_committish(argv[1], &oid) &&
+		   get_oid_committish(argv[2], &oid)) {
+		strbuf_addf(&range1, "%s..%s", argv[0], argv[1]);
+		strbuf_addf(&range2, "%s..%s", argv[0], argv[2]);
+		strvec_pushv(&other_arg, argv + 3);
 	} else {
 		error(_("need two commit ranges"));
 		usage_with_options(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..f2821a69b6f 100755
--- a/t/t3206-range-diff.sh
+++ b/t/t3206-range-diff.sh
@@ -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 &&
-- 
gitgitgadget

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/2] range-diff: optionally accept a pathspec
  2022-08-23 12:35 ` [PATCH 2/2] range-diff: optionally accept a pathspec Johannes Schindelin via GitGitGadget
@ 2022-08-24 21:00   ` Junio C Hamano
  0 siblings, 0 replies; 10+ messages in thread
From: Junio C Hamano @ 2022-08-24 21:00 UTC (permalink / raw)
  To: Johannes Schindelin via GitGitGadget; +Cc: git, Johannes Schindelin

"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
writes:

> From: Johannes Schindelin <johannes.schindelin@gmx.de>
>
> 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 <johannes.schindelin@gmx.de>
> ---

It is excellent that this now takes pathspec to sparsify the
history.

The implementation looks, eh, a bit dirty with obvious repetitions
in the "..." case and two-ranges cases.  Three-arg cases sort-of
looks different but that is because the original one does not even
bother to ensure argv[0] and argv[1] are objects, while the new one
does, so they are essentially doing the same things.

> 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=<factor>]
>  	[--left-only | --right-only]
>  	( <range1> <range2> | <rev1>...<rev2> | <base> <rev1> <rev2> )
> +	[[--] <path>...]

OK.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v2 0/3] Allow passing pathspecs to git range-diff
  2022-08-23 12:35 [PATCH 0/2] Allow passing pathspecs to git range-diff Johannes Schindelin via GitGitGadget
  2022-08-23 12:35 ` [PATCH 1/2] range-diff: reorder argument handling Johannes Schindelin via GitGitGadget
  2022-08-23 12:35 ` [PATCH 2/2] range-diff: optionally accept a pathspec Johannes Schindelin via GitGitGadget
@ 2022-08-26  9:39 ` Johannes Schindelin via GitGitGadget
  2022-08-26  9:39   ` [PATCH v2 1/3] range-diff: reorder argument handling Johannes Schindelin via GitGitGadget
                     ` (2 more replies)
  2 siblings, 3 replies; 10+ messages in thread
From: Johannes Schindelin via GitGitGadget @ 2022-08-26  9:39 UTC (permalink / raw)
  To: git; +Cc: Johannes Schindelin

I just had the need to find out upstream commits corresponding to a handful
of backported commits, and most importantly, identify upstream commits
touching a given file that had not yet been backported.

This new mode helped me identify them.

Changes since v1:

 * The command-line parameter parsing now avoids duplicating code as much as
   possible.
 * This also fixes a bug where git range-diff <incorrect-symmetric-range> --
   <pathspec> was mistaken for using the three-revision stanza.
 * Consistent validation of the command-line arguments has been extracted
   into its own patch.
 * Sadly, these changes make the overall diff much larger. I hope that the
   readability is worth that price.

Johannes Schindelin (3):
  range-diff: reorder argument handling
  range-diff: consistently validate the arguments
  range-diff: optionally accept pathspecs

 Documentation/git-range-diff.txt |   4 ++
 builtin/range-diff.c             | 101 +++++++++++++++++++++++--------
 range-diff.c                     |   2 +-
 t/t3206-range-diff.sh            |  13 +++-
 4 files changed, 94 insertions(+), 26 deletions(-)


base-commit: 795ea8776befc95ea2becd8020c7a284677b4161
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1335%2Fdscho%2Frange-diff-with-pathspec-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1335/dscho/range-diff-with-pathspec-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/1335

Range-diff vs v1:

 1:  7fe4f228ae0 ! 1:  150f29a1c48 range-diff: reorder argument handling
     @@ Commit message
          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 ascending
     +    ranges, we need to order these cases by argument count, in descending
          order.
      
          This patch is best viewed with `--color-moved`.
     @@ builtin/range-diff.c: int cmd_range_diff(int argc, const char **argv, const char
       		diffopt.use_color = 1;
       
      -	if (argc == 2) {
     --		if (!is_range_diff_range(argv[0]))
     --			die(_("not a commit range: '%s'"), argv[0]);
     --		strbuf_addstr(&range1, argv[0]);
     --
     --		if (!is_range_diff_range(argv[1]))
     --			die(_("not a commit range: '%s'"), argv[1]);
     --		strbuf_addstr(&range2, argv[1]);
     ++	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]);
     +@@ builtin/range-diff.c: 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) {
     -+	if (argc == 1) {
     + 	} else if (argc == 1) {
       		const char *b = strstr(argv[0], "..."), *a = argv[0];
       		int a_len;
     - 
     -@@ builtin/range-diff.c: 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 if (argc == 2) {
     -+		if (!is_range_diff_range(argv[0]))
     -+			die(_("not a commit range: '%s'"), argv[0]);
     -+		strbuf_addstr(&range1, argv[0]);
     -+
     -+		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 {
     - 		error(_("need two commit ranges"));
     - 		usage_with_options(builtin_range_diff_usage, options);
 -:  ----------- > 2:  4cd7f09557c range-diff: consistently validate the arguments
 2:  064b147451b ! 3:  a52ad40e015 range-diff: optionally accept a pathspec
     @@ Metadata
      Author: Johannes Schindelin <Johannes.Schindelin@gmx.de>
      
       ## Commit message ##
     -    range-diff: optionally accept a pathspec
     +    range-diff: optionally accept pathspecs
      
          The `git range-diff` command can be quite expensive, which is not a
          surprise given that the underlying algorithm to match up pairs of
     @@ Documentation/git-range-diff.txt: DESCRIPTION
      
       ## builtin/range-diff.c ##
      @@ builtin/range-diff.c: int cmd_range_diff(int argc, const char **argv, const char *prefix)
     + 		OPT_END()
     + 	};
       	struct option *options;
     - 	int res = 0;
     +-	int res = 0;
     ++	int i, dash_dash = -1, res = 0;
       	struct strbuf range1 = STRBUF_INIT, range2 = STRBUF_INIT;
     -+	struct object_id oid;
     -+	const char *p;
     + 	struct object_id oid;
     ++	const char *three_dots = NULL;
       
       	git_config(git_diff_ui_config, NULL);
       
     @@ builtin/range-diff.c: int cmd_range_diff(int argc, const char **argv, const char
       	diff_setup_done(&diffopt);
       
      @@ builtin/range-diff.c: 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 if (argc > 1 && (p = strstr(argv[0], "..."))) {
     -+		const char *a = argv[0];
     -+		int a_len = (int)(p - a);
     -+
     -+		if (!a_len) {
     -+			a = "HEAD";
     -+			a_len = strlen(a);
     + 	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;
      +		}
     -+		p += 3;
     -+		if (!*p)
     -+			p = "HEAD";
     -+		strbuf_addf(&range1, "%s..%.*s", p, a_len, a);
     -+		strbuf_addf(&range2, "%.*s..%s", a_len, a, p);
     -+		strvec_pushv(&other_arg, argv + 1);
     - 	} else if (argc == 2) {
     - 		if (!is_range_diff_range(argv[0]))
     - 			die(_("not a commit range: '%s'"), argv[0]);
     ++
     ++	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]);
      @@ builtin/range-diff.c: 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 > 2 &&
     -+	    is_range_diff_range(argv[0]) && is_range_diff_range(argv[1])) {
     -+		strbuf_addstr(&range1, argv[0]);
     -+		strbuf_addstr(&range2, argv[1]);
     -+		strvec_pushv(&other_arg, argv + 2);
     - 	} 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 > 3 &&
     -+		   get_oid_committish(argv[0], &oid) &&
     -+		   get_oid_committish(argv[1], &oid) &&
     -+		   get_oid_committish(argv[2], &oid)) {
     -+		strbuf_addf(&range1, "%s..%s", argv[0], argv[1]);
     -+		strbuf_addf(&range2, "%s..%s", argv[0], argv[2]);
     -+		strvec_pushv(&other_arg, argv + 3);
     - 	} else {
     - 		error(_("need two commit ranges"));
     - 		usage_with_options(builtin_range_diff_usage, options);
     +-	} 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]);
     +@@ builtin/range-diff.c: 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);
      
       ## range-diff.c ##
      @@ range-diff.c: static int read_patches(const char *range, struct string_list *list,
     @@ range-diff.c: static int read_patches(const char *range, struct string_list *lis
       	cp.git_cmd = 1;
      
       ## t/t3206-range-diff.sh ##
     +@@ t/t3206-range-diff.sh: test_expect_success 'A^! and A^-<n> (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
     + '
     + 
      @@ t/t3206-range-diff.sh: test_expect_success '--left-only/--right-only' '
       	test_cmp expect actual
       '

-- 
gitgitgadget

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v2 1/3] range-diff: reorder argument handling
  2022-08-26  9:39 ` [PATCH v2 0/3] Allow passing pathspecs to git range-diff Johannes Schindelin via GitGitGadget
@ 2022-08-26  9:39   ` Johannes Schindelin via GitGitGadget
  2022-08-26  9:39   ` [PATCH v2 2/3] range-diff: consistently validate the arguments Johannes Schindelin via GitGitGadget
  2022-08-26  9:39   ` [PATCH v2 3/3] range-diff: optionally accept pathspecs Johannes Schindelin via GitGitGadget
  2 siblings, 0 replies; 10+ messages in thread
From: Johannes Schindelin via GitGitGadget @ 2022-08-26  9:39 UTC (permalink / raw)
  To: git; +Cc: Johannes Schindelin, Johannes Schindelin

From: Johannes Schindelin <johannes.schindelin@gmx.de>

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 <johannes.schindelin@gmx.de>
---
 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;
-- 
gitgitgadget


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 2/3] range-diff: consistently validate the arguments
  2022-08-26  9:39 ` [PATCH v2 0/3] Allow passing pathspecs to git range-diff Johannes Schindelin via GitGitGadget
  2022-08-26  9:39   ` [PATCH v2 1/3] range-diff: reorder argument handling Johannes Schindelin via GitGitGadget
@ 2022-08-26  9:39   ` Johannes Schindelin via GitGitGadget
  2022-08-26 16:54     ` Junio C Hamano
  2022-08-26  9:39   ` [PATCH v2 3/3] range-diff: optionally accept pathspecs Johannes Schindelin via GitGitGadget
  2 siblings, 1 reply; 10+ messages in thread
From: Johannes Schindelin via GitGitGadget @ 2022-08-26  9:39 UTC (permalink / raw)
  To: git; +Cc: Johannes Schindelin, Johannes Schindelin

From: Johannes Schindelin <johannes.schindelin@gmx.de>

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 <johannes.schindelin@gmx.de>
---
 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;
-- 
gitgitgadget


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 3/3] range-diff: optionally accept pathspecs
  2022-08-26  9:39 ` [PATCH v2 0/3] Allow passing pathspecs to git range-diff Johannes Schindelin via GitGitGadget
  2022-08-26  9:39   ` [PATCH v2 1/3] range-diff: reorder argument handling Johannes Schindelin via GitGitGadget
  2022-08-26  9:39   ` [PATCH v2 2/3] range-diff: consistently validate the arguments Johannes Schindelin via GitGitGadget
@ 2022-08-26  9:39   ` Johannes Schindelin via GitGitGadget
  2022-08-26 17:02     ` Junio C Hamano
  2 siblings, 1 reply; 10+ messages in thread
From: Johannes Schindelin via GitGitGadget @ 2022-08-26  9:39 UTC (permalink / raw)
  To: git; +Cc: Johannes Schindelin, Johannes Schindelin

From: Johannes Schindelin <johannes.schindelin@gmx.de>

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 <johannes.schindelin@gmx.de>
---
 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=<factor>]
 	[--left-only | --right-only]
 	( <range1> <range2> | <rev1>...<rev2> | <base> <rev1> <rev2> )
+	[[--] <path>...]
 
 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 `<path>` 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^-<n> (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 &&
-- 
gitgitgadget

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 2/3] range-diff: consistently validate the arguments
  2022-08-26  9:39   ` [PATCH v2 2/3] range-diff: consistently validate the arguments Johannes Schindelin via GitGitGadget
@ 2022-08-26 16:54     ` Junio C Hamano
  0 siblings, 0 replies; 10+ messages in thread
From: Junio C Hamano @ 2022-08-26 16:54 UTC (permalink / raw)
  To: Johannes Schindelin via GitGitGadget; +Cc: git, Johannes Schindelin

"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
writes:

> From: Johannes Schindelin <johannes.schindelin@gmx.de>
>
> 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 <johannes.schindelin@gmx.de>
> ---
>  builtin/range-diff.c | 41 +++++++++++++++++++++++++++++------------
>  1 file changed, 29 insertions(+), 12 deletions(-)

Very nice.  The updated series is worth having if only for this
step.  Very very pleasing.


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 3/3] range-diff: optionally accept pathspecs
  2022-08-26  9:39   ` [PATCH v2 3/3] range-diff: optionally accept pathspecs Johannes Schindelin via GitGitGadget
@ 2022-08-26 17:02     ` Junio C Hamano
  0 siblings, 0 replies; 10+ messages in thread
From: Junio C Hamano @ 2022-08-26 17:02 UTC (permalink / raw)
  To: Johannes Schindelin via GitGitGadget; +Cc: git, Johannes Schindelin

"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
writes:

> +	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]);

Very reasonable.  We won't ever have "--" on the command line as
anything but a dash-dash (i.e. there is no option to the command
that can take any string), and thanks to the previous step, this
addition falls in place very naturally.  Very nicely done.

Will replace.  I _think_ this is ready for 'next', but let's see if
others spot problems for a few days.

THanks.

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2022-08-26 17:02 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-23 12:35 [PATCH 0/2] Allow passing pathspecs to git range-diff Johannes Schindelin via GitGitGadget
2022-08-23 12:35 ` [PATCH 1/2] range-diff: reorder argument handling Johannes Schindelin via GitGitGadget
2022-08-23 12:35 ` [PATCH 2/2] range-diff: optionally accept a pathspec Johannes Schindelin via GitGitGadget
2022-08-24 21:00   ` Junio C Hamano
2022-08-26  9:39 ` [PATCH v2 0/3] Allow passing pathspecs to git range-diff Johannes Schindelin via GitGitGadget
2022-08-26  9:39   ` [PATCH v2 1/3] range-diff: reorder argument handling Johannes Schindelin via GitGitGadget
2022-08-26  9:39   ` [PATCH v2 2/3] range-diff: consistently validate the arguments Johannes Schindelin via GitGitGadget
2022-08-26 16:54     ` Junio C Hamano
2022-08-26  9:39   ` [PATCH v2 3/3] range-diff: optionally accept pathspecs Johannes Schindelin via GitGitGadget
2022-08-26 17:02     ` Junio C Hamano

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).