blame: enable funcname blaming with userdiff driver

In blame.c::cmd_blame, we send the 'path' field of the 'sb' 'struct
blame_scoreboard' as the 'path' argument to
'line-range.c::parse_range_arg', but 'sb.path' is not set yet; it's set
to the local variable 'path' a few lines later at line 1137.

This 'path' argument is only used in 'parse_range_arg' if we are blaming
a funcname, i.e. `git blame -L :<funcname> <path>`, and in that case it
is sent to 'parse_range_funcname', where it is used to determine if a
userdiff driver should be used for said <path> to match the given
funcname.

Since 'path' is yet unset, the userdiff driver is never used, so we fall
back to the default funcname regex, which is usually not appropriate for
paths that are set to use a specific userdiff driver, and thus either we
match some unrelated lines, or we die with

    fatal: -L parameter '<funcname>' starting at line 1: no match

This has been the case ever since `git blame` learned to blame a
funcname in 13b8f68c1f (log -L: :pattern:file syntax to find by
funcname, 2013-03-28).

Enable funcname blaming for paths using specific userdiff drivers by
initializing 'sb.path' earlier in 'cmd_blame', when some of its other
fields are initialized, so that it is set when passed to
'parse_range_arg'.

Add a regression test in 'annotate-tests.sh', which is sourced in
t8001-annotate.sh and t8002-blame.sh, leveraging an existing file used
to test the userdiff patterns in t4018-diff-funcname.

Also, use 'sb.path' instead of 'path' when constructing the error
message at line 1114, for consistency.

Signed-off-by: Philippe Blain <levraiphilippeblain@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Philippe Blain 2020-11-01 17:28:45 +00:00 коммит произвёл Junio C Hamano
Родитель 180d641d7d
Коммит 9466e3809d
2 изменённых файлов: 20 добавлений и 2 удалений

Просмотреть файл

@ -1083,6 +1083,7 @@ parse_done:
sb.contents_from = contents_from;
sb.reverse = reverse;
sb.repo = the_repository;
sb.path = path;
build_ignorelist(&sb, &ignore_revs_file_list, &ignore_rev_list);
string_list_clear(&ignore_revs_file_list, 0);
string_list_clear(&ignore_rev_list, 0);
@ -1112,7 +1113,7 @@ parse_done:
if ((!lno && (top || bottom)) || lno < bottom)
die(Q_("file %s has only %lu line",
"file %s has only %lu lines",
lno), path, lno);
lno), sb.path, lno);
if (bottom < 1)
bottom = 1;
if (top < 1 || lno < top)
@ -1137,7 +1138,6 @@ parse_done:
string_list_clear(&range_list, 0);
sb.ent = NULL;
sb.path = path;
if (blame_move_score)
sb.move_score = blame_move_score;

Просмотреть файл

@ -479,6 +479,24 @@ test_expect_success 'blame -L ^:RE (absolute: end-of-file)' '
check_count -f hello.c -L$n -L^:ma.. F 4 G 1 H 1
'
test_expect_success 'setup -L :funcname with userdiff driver' '
echo "fortran-* diff=fortran" >.gitattributes &&
fortran_file=fortran-external-function &&
orig_file="$TEST_DIRECTORY/t4018/$fortran_file" &&
cp $orig_file . &&
git add $fortran_file &&
GIT_AUTHOR_NAME="A" GIT_AUTHOR_EMAIL="A@test.git" \
git commit -m "add fortran file" &&
sed -e "s/ChangeMe/IWasChanged/" <"$orig_file" >$fortran_file &&
git add $fortran_file &&
GIT_AUTHOR_NAME="B" GIT_AUTHOR_EMAIL="B@test.git" \
git commit -m "change fortran file"
'
test_expect_success 'blame -L :funcname with userdiff driver' '
check_count -f fortran-external-function -L:RIGHT A 7 B 1
'
test_expect_success 'setup incremental' '
(
GIT_AUTHOR_NAME=I &&