mirror of
https://github.com/git/git
synced 2024-08-25 02:35:46 +00:00
Merge branch 'jk/for-each-reflog-ent-reverse'
The code that reads the reflog from the newer to the older entries did not handle an entry that crosses a boundary of block it uses to read them correctly. * 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
This commit is contained in:
commit
6f3abb7a87
51
refs.c
51
refs.c
|
@ -3413,29 +3413,54 @@ int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn, void
|
||||||
|
|
||||||
bp = find_beginning_of_line(buf, scanp);
|
bp = find_beginning_of_line(buf, scanp);
|
||||||
|
|
||||||
if (*bp != '\n') {
|
if (*bp == '\n') {
|
||||||
strbuf_splice(&sb, 0, 0, buf, endp - buf);
|
|
||||||
if (pos)
|
|
||||||
break; /* need to fill another block */
|
|
||||||
scanp = buf - 1; /* leave loop */
|
|
||||||
} else {
|
|
||||||
/*
|
/*
|
||||||
* (bp + 1) thru endp is the beginning of the
|
* The newline is the end of the previous line,
|
||||||
* current line we have in sb
|
* so we know we have complete line starting
|
||||||
|
* at (bp + 1). Prefix it onto any prior data
|
||||||
|
* we collected for the line and process it.
|
||||||
*/
|
*/
|
||||||
strbuf_splice(&sb, 0, 0, bp + 1, endp - (bp + 1));
|
strbuf_splice(&sb, 0, 0, bp + 1, endp - (bp + 1));
|
||||||
scanp = bp;
|
scanp = bp;
|
||||||
endp = bp + 1;
|
endp = bp + 1;
|
||||||
}
|
ret = show_one_reflog_ent(&sb, fn, cb_data);
|
||||||
ret = show_one_reflog_ent(&sb, fn, cb_data);
|
strbuf_reset(&sb);
|
||||||
strbuf_reset(&sb);
|
if (ret)
|
||||||
if (ret)
|
break;
|
||||||
|
} else if (!pos) {
|
||||||
|
/*
|
||||||
|
* We are at the start of the buffer, and the
|
||||||
|
* start of the file; there is no previous
|
||||||
|
* line, and we have everything for this one.
|
||||||
|
* Process it, and we can end the loop.
|
||||||
|
*/
|
||||||
|
strbuf_splice(&sb, 0, 0, buf, endp - buf);
|
||||||
|
ret = show_one_reflog_ent(&sb, fn, cb_data);
|
||||||
|
strbuf_reset(&sb);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bp == buf) {
|
||||||
|
/*
|
||||||
|
* We are at the start of the buffer, and there
|
||||||
|
* is more file to read backwards. Which means
|
||||||
|
* we are in the middle of a line. Note that we
|
||||||
|
* may get here even if *bp was a newline; that
|
||||||
|
* just means we are at the exact end of the
|
||||||
|
* previous line, rather than some spot in the
|
||||||
|
* middle.
|
||||||
|
*
|
||||||
|
* Save away what we have to be combined with
|
||||||
|
* the data from the next read.
|
||||||
|
*/
|
||||||
|
strbuf_splice(&sb, 0, 0, buf, endp - buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (!ret && sb.len)
|
if (!ret && sb.len)
|
||||||
ret = show_one_reflog_ent(&sb, fn, cb_data);
|
die("BUG: reverse reflog parser had leftover data");
|
||||||
|
|
||||||
fclose(logfp);
|
fclose(logfp);
|
||||||
strbuf_release(&sb);
|
strbuf_release(&sb);
|
||||||
|
|
|
@ -287,4 +287,34 @@ test_expect_success 'stale dirs do not cause d/f conflicts (reflogs off)' '
|
||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
# Triggering the bug detected by this test requires a newline to fall
|
||||||
|
# exactly BUFSIZ-1 bytes from the end of the file. We don't know
|
||||||
|
# what that value is, since it's platform dependent. However, if
|
||||||
|
# we choose some value N, we also catch any D which divides N evenly
|
||||||
|
# (since we will read backwards in chunks of D). So we choose 8K,
|
||||||
|
# which catches glibc (with an 8K BUFSIZ) and *BSD (1K).
|
||||||
|
#
|
||||||
|
# Each line is 114 characters, so we need 75 to still have a few before the
|
||||||
|
# last 8K. The 89-character padding on the final entry lines up our
|
||||||
|
# newline exactly.
|
||||||
|
test_expect_success 'parsing reverse reflogs at BUFSIZ boundaries' '
|
||||||
|
git checkout -b reflogskip &&
|
||||||
|
z38=00000000000000000000000000000000000000 &&
|
||||||
|
ident="abc <xyz> 0000000001 +0000" &&
|
||||||
|
for i in $(test_seq 1 75); do
|
||||||
|
printf "$z38%02d $z38%02d %s\t" $i $(($i+1)) "$ident" &&
|
||||||
|
if test $i = 75; then
|
||||||
|
for j in $(test_seq 1 89); do
|
||||||
|
printf X
|
||||||
|
done
|
||||||
|
else
|
||||||
|
printf X
|
||||||
|
fi &&
|
||||||
|
printf "\n"
|
||||||
|
done >.git/logs/refs/heads/reflogskip &&
|
||||||
|
git rev-parse reflogskip@{73} >actual &&
|
||||||
|
echo ${z38}03 >expect &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
|
Loading…
Reference in a new issue