diff mbox series

revision: fix --left/right-only use with unrelated histories

Message ID 20250330055809.1019090-1-m@lfurio.us (mailing list archive)
State Superseded
Headers show
Series revision: fix --left/right-only use with unrelated histories | expand

Commit Message

Matt Hunter March 30, 2025, 5:49 a.m. UTC
This is a similar fix as 023756f4eb (revision walker: --cherry-pick is a
limited operation), but for the --left-only and --right-only options.

When computing a symmetric difference between two unrelated histories,
no suitable merge base exists, and so no boundary commit is flagged as
UNINTERESTING.  Previously, we relied on the presence of such boundary
to trigger limiting and thus consideration of either "revs->left_only"
or "revs->right_only".

A number of other entries in the option parser have started including
overrides for "revs->limited = 1".  Do the same for these options.

Signed-off-by: Matt Hunter <m@lfurio.us>
---

Patch applies to the current maint branch (git v2.49.0).

I made a best guess at what the most logical home for this test case
should be, so please let me know if somewhere else is preferred.  All
tests pass when this is cherry-picked to seen.  There is only a minor
conflict, as a few different tests have appeared in this same spot.

 revision.c               |  2 ++
 t/t6000-rev-list-misc.sh | 12 ++++++++++++
 2 files changed, 14 insertions(+)


base-commit: 683c54c999c301c2cd6f715c411407c413b1d84e

Comments

Johannes Sixt March 30, 2025, 8:31 a.m. UTC | #1
Am 30.03.25 um 07:49 schrieb Matt Hunter:
> +	test $(comm -12 <(sort head) <(sort cmp) | wc -l) = "0"

Process substitution does not work on Windows. Please use temporary files.

-- Hannes
Phillip Wood March 30, 2025, 10:11 a.m. UTC | #2
Hi Matt

On 30/03/2025 06:49, Matt Hunter wrote:
> +test_expect_success 'rev-list one-sided unrelated symmetric diff' '
> +	test_tick &&
> +	git commit --allow-empty -m xyz &&
> +	git branch cmp &&
> +	git rebase --force-rebase --root &&
> +
> +	git rev-list --left-only  HEAD...cmp >head &&
> +	git rev-list --right-only HEAD...cmp >cmp  &&
> +
> +	test $(comm -12 <(sort head) <(sort cmp) | wc -l) = "0"

Thank you for adding a test. We have a helper function test_line_count 
which provides a helpful debugging message if the comparison fails. 
Using that and avoiding process substitutions we'd write

	sort head >sorted_head &&
	sort cmp >sorted_cmp &&
	comm -12 sorted_head sorted_cmp >actual &&
	test_line_count = 0 actual

Thanks

Phillip

> +
>   test_done
> 
> base-commit: 683c54c999c301c2cd6f715c411407c413b1d84e
Matt Hunter March 30, 2025, 10:54 a.m. UTC | #3
On Sun Mar 30, 2025 at 6:11 AM EDT, Phillip Wood wrote:
> Thank you for adding a test. We have a helper function test_line_count 
> which provides a helpful debugging message if the comparison fails. 
> Using that and avoiding process substitutions we'd write
>
> 	sort head >sorted_head &&
> 	sort cmp >sorted_cmp &&
> 	comm -12 sorted_head sorted_cmp >actual &&
> 	test_line_count = 0 actual
Thanks for that helper tip.  I was just about to send a v2 when your
message came in, so I'm getting that incorporated now.

By the way, I had originally wanted to write test assertions that
checked the actual number of commit ids returned from each of the two
calls to rev-list - something like:

    git rev-list --X-only HEAD...cmp >file &&
    test_line_count = N file

But since I'm not very familiar with this test harness yet, I couldn't
actually figure the correct value for N.  It's not 1 (the commit made in
my test body), and it's not 2 (that commit, plus the one from the setup
case at the top of the file).  Any appropriate higher value wasn't
obvious.

So I switched to what you saw in my v1.  Maybe this "no commit ids in
common" test is actually the stronger assertion?
Junio C Hamano April 1, 2025, 9:56 a.m. UTC | #4
Johannes Sixt <j6t@kdbg.org> writes:

> Am 30.03.25 um 07:49 schrieb Matt Hunter:
>> +	test $(comm -12 <(sort head) <(sort cmp) | wc -l) = "0"
>
> Process substitution does not work on Windows. Please use temporary files.

Also it is not portable across POSIX compilant shells (IIRC it is a
bash-ism).
Phillip Wood April 2, 2025, 1:12 p.m. UTC | #5
Hi Matt

On 30/03/2025 11:54, Matt Hunter wrote:
> On Sun Mar 30, 2025 at 6:11 AM EDT, Phillip Wood wrote:
>> Thank you for adding a test. We have a helper function test_line_count
>> which provides a helpful debugging message if the comparison fails.
>> Using that and avoiding process substitutions we'd write
>>
>> 	sort head >sorted_head &&
>> 	sort cmp >sorted_cmp &&
>> 	comm -12 sorted_head sorted_cmp >actual &&
>> 	test_line_count = 0 actual
> Thanks for that helper tip.  I was just about to send a v2 when your
> message came in, so I'm getting that incorporated now.
> 
> By the way, I had originally wanted to write test assertions that
> checked the actual number of commit ids returned from each of the two
> calls to rev-list - something like:
> 
>      git rev-list --X-only HEAD...cmp >file &&
>      test_line_count = N file
> 
> But since I'm not very familiar with this test harness yet, I couldn't
> actually figure the correct value for N.  It's not 1 (the commit made in
> my test body), and it's not 2 (that commit, plus the one from the setup
> case at the top of the file).  Any appropriate higher value wasn't
> obvious.

Each test in a given file runs in the same repository (this is a 
performance optimization) so the number of commits will depend on what 
the previous tests have done. Usually there is a setup test at the start 
of the file which creates some commits with tags. Individual tests can 
then use those tags to establish a known state.

Best Wishes

Phillip


> So I switched to what you saw in my v1.  Maybe this "no commit ids in
> common" test is actually the stronger assertion?
diff mbox series

Patch

diff --git a/revision.c b/revision.c
index c4390f0938..e045445bc3 100644
--- a/revision.c
+++ b/revision.c
@@ -2488,10 +2488,12 @@  static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
 			die(_("options '%s' and '%s' cannot be used together"),
 			    "--left-only", "--right-only/--cherry");
 		revs->left_only = 1;
+		revs->limited = 1;
 	} else if (!strcmp(arg, "--right-only")) {
 		if (revs->left_only)
 			die(_("options '%s' and '%s' cannot be used together"), "--right-only", "--left-only");
 		revs->right_only = 1;
+		revs->limited = 1;
 	} else if (!strcmp(arg, "--cherry")) {
 		if (revs->left_only)
 			die(_("options '%s' and '%s' cannot be used together"), "--cherry", "--left-only");
diff --git a/t/t6000-rev-list-misc.sh b/t/t6000-rev-list-misc.sh
index 6289a2e8b0..58f1f746e0 100755
--- a/t/t6000-rev-list-misc.sh
+++ b/t/t6000-rev-list-misc.sh
@@ -182,4 +182,16 @@  test_expect_success 'rev-list --unpacked' '
 	test_cmp expect actual
 '
 
+test_expect_success 'rev-list one-sided unrelated symmetric diff' '
+	test_tick &&
+	git commit --allow-empty -m xyz &&
+	git branch cmp &&
+	git rebase --force-rebase --root &&
+
+	git rev-list --left-only  HEAD...cmp >head &&
+	git rev-list --right-only HEAD...cmp >cmp  &&
+
+	test $(comm -12 <(sort head) <(sort cmp) | wc -l) = "0"
+'
+
 test_done