mirror of
https://github.com/git/git.git
synced 2024-12-02 22:43:44 +08:00
ee6a998583
There are some memory leaks when cleaning up blame scoreboards. Fix those. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
440 lines
7.8 KiB
Bash
Executable File
440 lines
7.8 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
test_description='git blame ignore fuzzy heuristic'
|
|
|
|
TEST_PASSES_SANITIZE_LEAK=true
|
|
. ./test-lib.sh
|
|
|
|
pick_author='s/^[0-9a-f^]* *(\([^ ]*\) .*/\1/'
|
|
|
|
# Each test is composed of 4 variables:
|
|
# titleN - the test name
|
|
# aN - the initial content
|
|
# bN - the final content
|
|
# expectedN - the line numbers from aN that we expect git blame
|
|
# on bN to identify, or "Final" if bN itself should
|
|
# be identified as the origin of that line.
|
|
|
|
# We start at test 2 because setup will show as test 1
|
|
title2="Regression test for partially overlapping search ranges"
|
|
cat <<EOF >a2
|
|
1
|
|
2
|
|
3
|
|
abcdef
|
|
5
|
|
6
|
|
7
|
|
ijkl
|
|
9
|
|
10
|
|
11
|
|
pqrs
|
|
13
|
|
14
|
|
15
|
|
wxyz
|
|
17
|
|
18
|
|
19
|
|
EOF
|
|
cat <<EOF >b2
|
|
abcde
|
|
ijk
|
|
pqr
|
|
wxy
|
|
EOF
|
|
cat <<EOF >expected2
|
|
4
|
|
8
|
|
12
|
|
16
|
|
EOF
|
|
|
|
title3="Combine 3 lines into 2"
|
|
cat <<EOF >a3
|
|
if ((maxgrow==0) ||
|
|
( single_line_field && (field->dcols < maxgrow)) ||
|
|
(!single_line_field && (field->drows < maxgrow)))
|
|
EOF
|
|
cat <<EOF >b3
|
|
if ((maxgrow == 0) || (single_line_field && (field->dcols < maxgrow)) ||
|
|
(!single_line_field && (field->drows < maxgrow))) {
|
|
EOF
|
|
cat <<EOF >expected3
|
|
2
|
|
3
|
|
EOF
|
|
|
|
title4="Add curly brackets"
|
|
cat <<EOF >a4
|
|
if (rows) *rows = field->rows;
|
|
if (cols) *cols = field->cols;
|
|
if (frow) *frow = field->frow;
|
|
if (fcol) *fcol = field->fcol;
|
|
EOF
|
|
cat <<EOF >b4
|
|
if (rows) {
|
|
*rows = field->rows;
|
|
}
|
|
if (cols) {
|
|
*cols = field->cols;
|
|
}
|
|
if (frow) {
|
|
*frow = field->frow;
|
|
}
|
|
if (fcol) {
|
|
*fcol = field->fcol;
|
|
}
|
|
EOF
|
|
cat <<EOF >expected4
|
|
1
|
|
1
|
|
Final
|
|
2
|
|
2
|
|
Final
|
|
3
|
|
3
|
|
Final
|
|
4
|
|
4
|
|
Final
|
|
EOF
|
|
|
|
|
|
title5="Combine many lines and change case"
|
|
cat <<EOF >a5
|
|
for(row=0,pBuffer=field->buf;
|
|
row<height;
|
|
row++,pBuffer+=width )
|
|
{
|
|
if ((len = (int)( After_End_Of_Data( pBuffer, width ) - pBuffer )) > 0)
|
|
{
|
|
wmove( win, row, 0 );
|
|
waddnstr( win, pBuffer, len );
|
|
EOF
|
|
cat <<EOF >b5
|
|
for (Row = 0, PBuffer = field->buf; Row < Height; Row++, PBuffer += Width) {
|
|
if ((Len = (int)(afterEndOfData(PBuffer, Width) - PBuffer)) > 0) {
|
|
wmove(win, Row, 0);
|
|
waddnstr(win, PBuffer, Len);
|
|
EOF
|
|
cat <<EOF >expected5
|
|
1
|
|
5
|
|
7
|
|
8
|
|
EOF
|
|
|
|
title6="Rename and combine lines"
|
|
cat <<EOF >a6
|
|
bool need_visual_update = ((form != (FORM *)0) &&
|
|
(form->status & _POSTED) &&
|
|
(form->current==field));
|
|
|
|
if (need_visual_update)
|
|
Synchronize_Buffer(form);
|
|
|
|
if (single_line_field)
|
|
{
|
|
growth = field->cols * amount;
|
|
if (field->maxgrow)
|
|
growth = Minimum(field->maxgrow - field->dcols,growth);
|
|
field->dcols += growth;
|
|
if (field->dcols == field->maxgrow)
|
|
EOF
|
|
cat <<EOF >b6
|
|
bool NeedVisualUpdate = ((Form != (FORM *)0) && (Form->status & _POSTED) &&
|
|
(Form->current == field));
|
|
|
|
if (NeedVisualUpdate) {
|
|
synchronizeBuffer(Form);
|
|
}
|
|
|
|
if (SingleLineField) {
|
|
Growth = field->cols * amount;
|
|
if (field->maxgrow) {
|
|
Growth = Minimum(field->maxgrow - field->dcols, Growth);
|
|
}
|
|
field->dcols += Growth;
|
|
if (field->dcols == field->maxgrow) {
|
|
EOF
|
|
cat <<EOF >expected6
|
|
1
|
|
3
|
|
4
|
|
5
|
|
6
|
|
Final
|
|
7
|
|
8
|
|
10
|
|
11
|
|
12
|
|
Final
|
|
13
|
|
14
|
|
EOF
|
|
|
|
# Both lines match identically so position must be used to tie-break.
|
|
title7="Same line twice"
|
|
cat <<EOF >a7
|
|
abc
|
|
abc
|
|
EOF
|
|
cat <<EOF >b7
|
|
abcd
|
|
abcd
|
|
EOF
|
|
cat <<EOF >expected7
|
|
1
|
|
2
|
|
EOF
|
|
|
|
title8="Enforce line order"
|
|
cat <<EOF >a8
|
|
abcdef
|
|
ghijkl
|
|
ab
|
|
EOF
|
|
cat <<EOF >b8
|
|
ghijk
|
|
abcd
|
|
EOF
|
|
cat <<EOF >expected8
|
|
2
|
|
3
|
|
EOF
|
|
|
|
title9="Expand lines and rename variables"
|
|
cat <<EOF >a9
|
|
int myFunction(int ArgumentOne, Thing *ArgTwo, Blah XuglyBug) {
|
|
Squiggle FabulousResult = squargle(ArgumentOne, *ArgTwo,
|
|
XuglyBug) + EwwwGlobalWithAReallyLongNameYepTooLong;
|
|
return FabulousResult * 42;
|
|
}
|
|
EOF
|
|
cat <<EOF >b9
|
|
int myFunction(int argument_one, Thing *arg_asdfgh,
|
|
Blah xugly_bug) {
|
|
Squiggle fabulous_result = squargle(argument_one,
|
|
*arg_asdfgh, xugly_bug)
|
|
+ g_ewww_global_with_a_really_long_name_yep_too_long;
|
|
return fabulous_result * 42;
|
|
}
|
|
EOF
|
|
cat <<EOF >expected9
|
|
1
|
|
1
|
|
2
|
|
3
|
|
3
|
|
4
|
|
5
|
|
EOF
|
|
|
|
title10="Two close matches versus one less close match"
|
|
cat <<EOF >a10
|
|
abcdef
|
|
abcdef
|
|
ghijkl
|
|
EOF
|
|
cat <<EOF >b10
|
|
gh
|
|
abcdefx
|
|
EOF
|
|
cat <<EOF >expected10
|
|
Final
|
|
2
|
|
EOF
|
|
|
|
# The first line of b matches best with the last line of a, but the overall
|
|
# match is better if we match it with the first line of a.
|
|
title11="Piggy in the middle"
|
|
cat <<EOF >a11
|
|
abcdefg
|
|
ijklmn
|
|
abcdefgh
|
|
EOF
|
|
cat <<EOF >b11
|
|
abcdefghx
|
|
ijklm
|
|
EOF
|
|
cat <<EOF >expected11
|
|
1
|
|
2
|
|
EOF
|
|
|
|
title12="No trailing newline"
|
|
printf "abc\ndef" >a12
|
|
printf "abx\nstu" >b12
|
|
cat <<EOF >expected12
|
|
1
|
|
Final
|
|
EOF
|
|
|
|
title13="Reorder includes"
|
|
cat <<EOF >a13
|
|
#include "c.h"
|
|
#include "b.h"
|
|
#include "a.h"
|
|
#include "e.h"
|
|
#include "d.h"
|
|
EOF
|
|
cat <<EOF >b13
|
|
#include "a.h"
|
|
#include "b.h"
|
|
#include "c.h"
|
|
#include "d.h"
|
|
#include "e.h"
|
|
EOF
|
|
cat <<EOF >expected13
|
|
3
|
|
2
|
|
1
|
|
5
|
|
4
|
|
EOF
|
|
|
|
last_test=13
|
|
|
|
test_expect_success setup '
|
|
for i in $(test_seq 2 $last_test)
|
|
do
|
|
# Append each line in a separate commit to make it easy to
|
|
# check which original line the blame output relates to.
|
|
|
|
line_count=0 &&
|
|
while IFS= read line
|
|
do
|
|
line_count=$((line_count+1)) &&
|
|
echo "$line" >>"$i" &&
|
|
git add "$i" &&
|
|
test_tick &&
|
|
GIT_AUTHOR_NAME="$line_count" git commit -m "$line_count" || return 1
|
|
done <"a$i"
|
|
done &&
|
|
|
|
for i in $(test_seq 2 $last_test)
|
|
do
|
|
# Overwrite the files with the final content.
|
|
cp b$i $i &&
|
|
git add $i || return 1
|
|
done &&
|
|
test_tick &&
|
|
|
|
# Commit the final content all at once so it can all be
|
|
# referred to with the same commit ID.
|
|
GIT_AUTHOR_NAME=Final git commit -m Final &&
|
|
|
|
IGNOREME=$(git rev-parse HEAD)
|
|
'
|
|
|
|
for i in $(test_seq 2 $last_test); do
|
|
eval title="\$title$i"
|
|
test_expect_success "$title" \
|
|
"git blame -M9 --ignore-rev $IGNOREME $i >output &&
|
|
sed -e \"$pick_author\" output >actual &&
|
|
test_cmp expected$i actual"
|
|
done
|
|
|
|
# This invoked a null pointer dereference when the chunk callback was called
|
|
# with a zero length parent chunk and there were no more suspects.
|
|
test_expect_success 'Diff chunks with no suspects' '
|
|
test_write_lines xy1 A B C xy1 >file &&
|
|
git add file &&
|
|
test_tick &&
|
|
GIT_AUTHOR_NAME=1 git commit -m 1 &&
|
|
|
|
test_write_lines xy2 A B xy2 C xy2 >file &&
|
|
git add file &&
|
|
test_tick &&
|
|
GIT_AUTHOR_NAME=2 git commit -m 2 &&
|
|
REV_2=$(git rev-parse HEAD) &&
|
|
|
|
test_write_lines xy3 A >file &&
|
|
git add file &&
|
|
test_tick &&
|
|
GIT_AUTHOR_NAME=3 git commit -m 3 &&
|
|
REV_3=$(git rev-parse HEAD) &&
|
|
|
|
test_write_lines 1 1 >expected &&
|
|
|
|
git blame --ignore-rev $REV_2 --ignore-rev $REV_3 file >output &&
|
|
sed -e "$pick_author" output >actual &&
|
|
|
|
test_cmp expected actual
|
|
'
|
|
|
|
test_expect_success 'position matching' '
|
|
test_write_lines abc def >file2 &&
|
|
git add file2 &&
|
|
test_tick &&
|
|
GIT_AUTHOR_NAME=1 git commit -m 1 &&
|
|
|
|
test_write_lines abc def abc def >file2 &&
|
|
git add file2 &&
|
|
test_tick &&
|
|
GIT_AUTHOR_NAME=2 git commit -m 2 &&
|
|
|
|
test_write_lines abcx defx abcx defx >file2 &&
|
|
git add file2 &&
|
|
test_tick &&
|
|
GIT_AUTHOR_NAME=3 git commit -m 3 &&
|
|
REV_3=$(git rev-parse HEAD) &&
|
|
|
|
test_write_lines abcy defy abcx defx >file2 &&
|
|
git add file2 &&
|
|
test_tick &&
|
|
GIT_AUTHOR_NAME=4 git commit -m 4 &&
|
|
REV_4=$(git rev-parse HEAD) &&
|
|
|
|
test_write_lines 1 1 2 2 >expected &&
|
|
|
|
git blame --ignore-rev $REV_3 --ignore-rev $REV_4 file2 >output &&
|
|
sed -e "$pick_author" output >actual &&
|
|
|
|
test_cmp expected actual
|
|
'
|
|
|
|
# This fails if each blame entry is processed independently instead of
|
|
# processing each diff change in full.
|
|
test_expect_success 'preserve order' '
|
|
test_write_lines bcde >file3 &&
|
|
git add file3 &&
|
|
test_tick &&
|
|
GIT_AUTHOR_NAME=1 git commit -m 1 &&
|
|
|
|
test_write_lines bcde fghij >file3 &&
|
|
git add file3 &&
|
|
test_tick &&
|
|
GIT_AUTHOR_NAME=2 git commit -m 2 &&
|
|
|
|
test_write_lines bcde fghij abcd >file3 &&
|
|
git add file3 &&
|
|
test_tick &&
|
|
GIT_AUTHOR_NAME=3 git commit -m 3 &&
|
|
|
|
test_write_lines abcdx fghijx bcdex >file3 &&
|
|
git add file3 &&
|
|
test_tick &&
|
|
GIT_AUTHOR_NAME=4 git commit -m 4 &&
|
|
REV_4=$(git rev-parse HEAD) &&
|
|
|
|
test_write_lines abcdx fghijy bcdex >file3 &&
|
|
git add file3 &&
|
|
test_tick &&
|
|
GIT_AUTHOR_NAME=5 git commit -m 5 &&
|
|
REV_5=$(git rev-parse HEAD) &&
|
|
|
|
test_write_lines 1 2 3 >expected &&
|
|
|
|
git blame --ignore-rev $REV_4 --ignore-rev $REV_5 file3 >output &&
|
|
sed -e "$pick_author" output >actual &&
|
|
|
|
test_cmp expected actual
|
|
'
|
|
|
|
test_done
|