Skip to content

Commit 1c5bc69

Browse files
newrengitster
authored andcommitted
diffcore-delta: avoid ignoring final 'line' of file
hash_chars() would hash lines to integers, and store them in a spanhash, but cut lines at 64 characters. Thus, whenever it reached 64 characters or a newline, it would create a new spanhash. The problem is, the final part of the file might not end 64 characters after the previous 'line' and might not end with a newline. This could, for example, cause an 85-byte file with 12 lines and only the first character in the file differing to appear merely 23% similar rather than the expected 97%. Ensure the last line is included, and add a testcase that would have caught this problem. Signed-off-by: Elijah Newren <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ec58344 commit 1c5bc69

File tree

2 files changed

+28
-0
lines changed

2 files changed

+28
-0
lines changed

diffcore-delta.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ static struct spanhash_top *hash_chars(struct repository *r,
159159
n = 0;
160160
accum1 = accum2 = 0;
161161
}
162+
if (n > 0) {
163+
hashval = (accum1 + accum2 * 0x61) % HASHBASE;
164+
hash = add_spanhash(hash, hashval, n);
165+
}
162166
QSORT(hash->data, (size_t)1ul << hash->alloc_log2, spanhash_cmp);
163167
return hash;
164168
}

t/t4001-diff-rename.sh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,4 +286,28 @@ test_expect_success 'basename similarity vs best similarity' '
286286
test_cmp expected actual
287287
'
288288

289+
test_expect_success 'last line matters too' '
290+
{
291+
test_write_lines a 0 1 2 3 4 5 6 7 8 9 &&
292+
printf "git ignores final up to 63 characters if not newline terminated"
293+
} >no-final-lf &&
294+
git add no-final-lf &&
295+
git commit -m "original version of file with no final newline" &&
296+
297+
# Change ONLY the first character of the whole file
298+
{
299+
test_write_lines b 0 1 2 3 4 5 6 7 8 9 &&
300+
printf "git ignores final up to 63 characters if not newline terminated"
301+
} >no-final-lf &&
302+
git add no-final-lf &&
303+
git mv no-final-lf still-absent-final-lf &&
304+
git commit -a -m "rename no-final-lf -> still-absent-final-lf" &&
305+
git diff-tree -r -M --name-status HEAD^ HEAD >actual &&
306+
sed -e "s/^R[0-9]* /R /" actual >actual.munged &&
307+
cat >expected <<-\EOF &&
308+
R no-final-lf still-absent-final-lf
309+
EOF
310+
test_cmp expected actual.munged
311+
'
312+
289313
test_done

0 commit comments

Comments
 (0)