Merge branch 'sg/line-log-boundary-fixes'

A corner case bug in "git log -L..." has been corrected.

* sg/line-log-boundary-fixes:
  line-log: show all line ranges touched by the same diff range
  line-log: fix assertion error
main
Junio C Hamano 2025-09-18 10:07:01 -07:00
commit cf47560e94
8 changed files with 218 additions and 3 deletions

View File

@ -201,7 +201,7 @@ static void range_set_difference(struct range_set *out,
* b: ------| * b: ------|
*/ */
j++; j++;
if (j >= b->nr || end < b->ranges[j].start) { if (j >= b->nr || end <= b->ranges[j].start) {
/* /*
* b exhausted, or * b exhausted, or
* a: ----| * a: ----|
@ -408,7 +408,7 @@ static void diff_ranges_filter_touched(struct diff_ranges *out,
assert(out->target.nr == 0); assert(out->target.nr == 0);


for (i = 0; i < diff->target.nr; i++) { for (i = 0; i < diff->target.nr; i++) {
while (diff->target.ranges[i].start > rs->ranges[j].end) { while (diff->target.ranges[i].start >= rs->ranges[j].end) {
j++; j++;
if (j == rs->nr) if (j == rs->nr)
return; return;
@ -939,9 +939,18 @@ static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *rang
long t_cur = t_start; long t_cur = t_start;
unsigned int j_last; unsigned int j_last;


/*
* If a diff range touches multiple line ranges, then all
* those line ranges should be shown, so take a step back if
* the current line range is still in the previous diff range
* (even if only partially).
*/
if (j > 0 && diff->target.ranges[j-1].end > t_start)
j--;

while (j < diff->target.nr && diff->target.ranges[j].end < t_start) while (j < diff->target.nr && diff->target.ranges[j].end < t_start)
j++; j++;
if (j == diff->target.nr || diff->target.ranges[j].start > t_end) if (j == diff->target.nr || diff->target.ranges[j].start >= t_end)
continue; continue;


/* Scan ahead to determine the last diff that falls in this range */ /* Scan ahead to determine the last diff that falls in this range */

View File

@ -78,6 +78,8 @@ canned_test "-L :main:a.c -L 4,18:a.c simple" multiple-overlapping
canned_test "-L 4:a.c -L 8,12:a.c simple" multiple-superset canned_test "-L 4:a.c -L 8,12:a.c simple" multiple-superset
canned_test "-L 8,12:a.c -L 4:a.c simple" multiple-superset canned_test "-L 8,12:a.c -L 4:a.c simple" multiple-superset


canned_test "-L 10,16:b.c -L 18,26:b.c main" no-assertion-error

test_bad_opts "-L" "switch.*requires a value" test_bad_opts "-L" "switch.*requires a value"
test_bad_opts "-L b.c" "argument not .start,end:file" test_bad_opts "-L b.c" "argument not .start,end:file"
test_bad_opts "-L 1:" "argument not .start,end:file" test_bad_opts "-L 1:" "argument not .start,end:file"

View File

@ -102,3 +102,9 @@ diff --git a/a.c b/a.c
+ s++; + s++;
+ } + }
+} +}
@@ -0,0 +16,5 @@
+int main ()
+{
+ printf("%d\n", f(15));
+ return 0;
+}

View File

@ -0,0 +1,90 @@
commit 0d8dcfc6b968e06a27d5215bad1fdde3de9d6235
Author: Thomas Rast <trast@student.ethz.ch>
Date: Thu Feb 28 10:50:24 2013 +0100

move within the file

diff --git a/b.c b/b.c
--- a/b.c
+++ b/b.c
@@ -25,0 +18,9 @@
+long f(long x)
+{
+ int s = 0;
+ while (x) {
+ x /= 2;
+ s++;
+ }
+ return s;
+}

commit 4659538844daa2849b1a9e7d6fadb96fcd26fc83
Author: Thomas Rast <trast@student.ethz.ch>
Date: Thu Feb 28 10:48:43 2013 +0100

change back to complete line

diff --git a/a.c b/a.c
--- a/a.c
+++ b/a.c
@@ -18,5 +18,7 @@
int main ()
{
printf("%ld\n", f(15));
return 0;
-}
\ No newline at end of file
+}
+
+/* incomplete lines are bad! */

commit 100b61a6f2f720f812620a9d10afb3a960ccb73c
Author: Thomas Rast <trast@student.ethz.ch>
Date: Thu Feb 28 10:48:10 2013 +0100

change to an incomplete line at end

diff --git a/a.c b/a.c
--- a/a.c
+++ b/a.c
@@ -18,5 +18,5 @@
int main ()
{
printf("%ld\n", f(15));
return 0;
-}
+}
\ No newline at end of file

commit a6eb82647d5d67f893da442f8f9375fd89a3b1e2
Author: Thomas Rast <trast@student.ethz.ch>
Date: Thu Feb 28 10:45:16 2013 +0100

touch both functions

diff --git a/a.c b/a.c
--- a/a.c
+++ b/a.c
@@ -17,5 +17,5 @@
int main ()
{
- printf("%d\n", f(15));
+ printf("%ld\n", f(15));
return 0;
}

commit de4c48ae814792c02a49c4c3c0c757ae69c55f6a
Author: Thomas Rast <trast@student.ethz.ch>
Date: Thu Feb 28 10:44:48 2013 +0100

initial

diff --git a/a.c b/a.c
--- /dev/null
+++ b/a.c
@@ -0,0 +16,5 @@
+int main ()
+{
+ printf("%d\n", f(15));
+ return 0;
+}

View File

@ -100,3 +100,9 @@ diff --git a/a.c b/a.c
+ s++; + s++;
+ } + }
+} +}
@@ -0,0 +16,5 @@
+int main ()
+{
+ printf("%d\n", f(15));
+ return 0;
+}

View File

@ -102,3 +102,9 @@ diff --git a/a.c b/a.c
+ s++; + s++;
+ } + }
+} +}
@@ -0,0 +16,5 @@
+int main ()
+{
+ printf("%d\n", f(15));
+ return 0;
+}

View File

@ -0,0 +1,90 @@
commit eb871b8aa9aff323e484723039c9a92ab0266e060bc0ef2afb08fadda25c5ace
Author: Thomas Rast <trast@student.ethz.ch>
Date: Thu Feb 28 10:50:24 2013 +0100

move within the file

diff --git a/b.c b/b.c
--- a/b.c
+++ b/b.c
@@ -25,0 +18,9 @@
+long f(long x)
+{
+ int s = 0;
+ while (x) {
+ x /= 2;
+ s++;
+ }
+ return s;
+}

commit 5526ed05c2476b56af8b7be499e8f78bd50f490740733a9ca7e1f55878fa90a9
Author: Thomas Rast <trast@student.ethz.ch>
Date: Thu Feb 28 10:48:43 2013 +0100

change back to complete line

diff --git a/a.c b/a.c
--- a/a.c
+++ b/a.c
@@ -18,5 +18,7 @@
int main ()
{
printf("%ld\n", f(15));
return 0;
-}
\ No newline at end of file
+}
+
+/* incomplete lines are bad! */

commit 29f32ac3141c48b22803e5c4127b719917b67d0f8ca8c5248bebfa2a19f7da10
Author: Thomas Rast <trast@student.ethz.ch>
Date: Thu Feb 28 10:48:10 2013 +0100

change to an incomplete line at end

diff --git a/a.c b/a.c
--- a/a.c
+++ b/a.c
@@ -18,5 +18,5 @@
int main ()
{
printf("%ld\n", f(15));
return 0;
-}
+}
\ No newline at end of file

commit ccf97b9878189c40a981da50b15713bb80a35755326320ec80900caf22ced46f
Author: Thomas Rast <trast@student.ethz.ch>
Date: Thu Feb 28 10:45:16 2013 +0100

touch both functions

diff --git a/a.c b/a.c
--- a/a.c
+++ b/a.c
@@ -17,5 +17,5 @@
int main ()
{
- printf("%d\n", f(15));
+ printf("%ld\n", f(15));
return 0;
}

commit 1dd7e9b2b1699324b53b341e728653b913bc192a14dfea168c5b51f2b3d03592
Author: Thomas Rast <trast@student.ethz.ch>
Date: Thu Feb 28 10:44:48 2013 +0100

initial

diff --git a/a.c b/a.c
--- /dev/null
+++ b/a.c
@@ -0,0 +16,5 @@
+int main ()
+{
+ printf("%d\n", f(15));
+ return 0;
+}

View File

@ -100,3 +100,9 @@ diff --git a/a.c b/a.c
+ s++; + s++;
+ } + }
+} +}
@@ -0,0 +16,5 @@
+int main ()
+{
+ printf("%d\n", f(15));
+ return 0;
+}