Skip to content

Commit 417a5b2

Browse files
committed
Merge branch 'jk/for-each-reflog-ent-reverse' into maint
* jk/for-each-reflog-ent-reverse: for_each_reflog_ent_reverse: turn leftover check into assertion for_each_reflog_ent_reverse: fix newlines on block boundaries
2 parents 7ba4626 + 69216bf commit 417a5b2

File tree

2 files changed

+67
-12
lines changed

2 files changed

+67
-12
lines changed

refs.c

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3404,29 +3404,54 @@ int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn, void
34043404

34053405
bp = find_beginning_of_line(buf, scanp);
34063406

3407-
if (*bp != '\n') {
3408-
strbuf_splice(&sb, 0, 0, buf, endp - buf);
3409-
if (pos)
3410-
break; /* need to fill another block */
3411-
scanp = buf - 1; /* leave loop */
3412-
} else {
3407+
if (*bp == '\n') {
34133408
/*
3414-
* (bp + 1) thru endp is the beginning of the
3415-
* current line we have in sb
3409+
* The newline is the end of the previous line,
3410+
* so we know we have complete line starting
3411+
* at (bp + 1). Prefix it onto any prior data
3412+
* we collected for the line and process it.
34163413
*/
34173414
strbuf_splice(&sb, 0, 0, bp + 1, endp - (bp + 1));
34183415
scanp = bp;
34193416
endp = bp + 1;
3417+
ret = show_one_reflog_ent(&sb, fn, cb_data);
3418+
strbuf_reset(&sb);
3419+
if (ret)
3420+
break;
3421+
} else if (!pos) {
3422+
/*
3423+
* We are at the start of the buffer, and the
3424+
* start of the file; there is no previous
3425+
* line, and we have everything for this one.
3426+
* Process it, and we can end the loop.
3427+
*/
3428+
strbuf_splice(&sb, 0, 0, buf, endp - buf);
3429+
ret = show_one_reflog_ent(&sb, fn, cb_data);
3430+
strbuf_reset(&sb);
3431+
break;
34203432
}
3421-
ret = show_one_reflog_ent(&sb, fn, cb_data);
3422-
strbuf_reset(&sb);
3423-
if (ret)
3433+
3434+
if (bp == buf) {
3435+
/*
3436+
* We are at the start of the buffer, and there
3437+
* is more file to read backwards. Which means
3438+
* we are in the middle of a line. Note that we
3439+
* may get here even if *bp was a newline; that
3440+
* just means we are at the exact end of the
3441+
* previous line, rather than some spot in the
3442+
* middle.
3443+
*
3444+
* Save away what we have to be combined with
3445+
* the data from the next read.
3446+
*/
3447+
strbuf_splice(&sb, 0, 0, buf, endp - buf);
34243448
break;
3449+
}
34253450
}
34263451

34273452
}
34283453
if (!ret && sb.len)
3429-
ret = show_one_reflog_ent(&sb, fn, cb_data);
3454+
die("BUG: reverse reflog parser had leftover data");
34303455

34313456
fclose(logfp);
34323457
strbuf_release(&sb);

t/t1410-reflog.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,4 +287,34 @@ test_expect_success 'stale dirs do not cause d/f conflicts (reflogs off)' '
287287
test_cmp expect actual
288288
'
289289

290+
# Triggering the bug detected by this test requires a newline to fall
291+
# exactly BUFSIZ-1 bytes from the end of the file. We don't know
292+
# what that value is, since it's platform dependent. However, if
293+
# we choose some value N, we also catch any D which divides N evenly
294+
# (since we will read backwards in chunks of D). So we choose 8K,
295+
# which catches glibc (with an 8K BUFSIZ) and *BSD (1K).
296+
#
297+
# Each line is 114 characters, so we need 75 to still have a few before the
298+
# last 8K. The 89-character padding on the final entry lines up our
299+
# newline exactly.
300+
test_expect_success 'parsing reverse reflogs at BUFSIZ boundaries' '
301+
git checkout -b reflogskip &&
302+
z38=00000000000000000000000000000000000000 &&
303+
ident="abc <xyz> 0000000001 +0000" &&
304+
for i in $(test_seq 1 75); do
305+
printf "$z38%02d $z38%02d %s\t" $i $(($i+1)) "$ident" &&
306+
if test $i = 75; then
307+
for j in $(test_seq 1 89); do
308+
printf X
309+
done
310+
else
311+
printf X
312+
fi &&
313+
printf "\n"
314+
done >.git/logs/refs/heads/reflogskip &&
315+
git rev-parse reflogskip@{73} >actual &&
316+
echo ${z38}03 >expect &&
317+
test_cmp expect actual
318+
'
319+
290320
test_done

0 commit comments

Comments
 (0)