Commit 75203d03 by Patrick Steinhardt

blame_git: fix coalescing step never being executed

Since blame has been imported from git.git and had its first share of
refactorings in b6f60a4d (Clean up ported code, 2013-09-21), the code
is actually not doing the coalescing step of the generated blame. While
the code to do the coalescing does exist, it is never being called as
the function `git_blame__like_git` will directly return from its `while
(true)` loop.

The function that was being imported from git.git was the `assign_blame`
function from "builtin/blame.c" from 717d1462b (git-blame --incremental,
2007-01-28), which hasn't really changed much. Upon taking an initial
look, one can seet hat `coalesce` is actually never getting called in
`assign_blame`, as well, so one may assume that not calling `coalesce`
by accident is actually the right thing. But it is not, as `coalesce` is
being called ever since cee7f245d (git-pickaxe: blame rewritten.,
2006-10-19) after the blame has been done in the caller of
`assign_blame`. Thus we can conclude the code of libgit2 is actually
buggy since forever.

To fix the issue, simply break out of the loop instead of doing a direct
return. Note that this does not alter behaviour in any way visible to
our tests, which is unfortunate. But in order to not diverge from what
git.git does, I'd rather adapt to how it is being done upstream in order
to avoid breaking certain edge cases than to just remove that code.
parent 9e8bc726
......@@ -623,6 +623,8 @@ static void coalesce(git_blame *blame)
int git_blame__like_git(git_blame *blame, uint32_t opt)
{
int error = 0;
while (true) {
git_blame__entry *ent;
git_blame__origin *suspect = NULL;
......@@ -632,13 +634,13 @@ int git_blame__like_git(git_blame *blame, uint32_t opt)
if (!ent->guilty)
suspect = ent->suspect;
if (!suspect)
return 0; /* all done */
break;
/* We'll use this suspect later in the loop, so hold on to it for now. */
origin_incref(suspect);
if (pass_blame(blame, suspect, opt) < 0)
return -1;
if ((error = pass_blame(blame, suspect, opt)) < 0)
break;
/* Take responsibility for the remaining entries */
for (ent = blame->ent; ent; ent = ent->next) {
......@@ -652,9 +654,10 @@ int git_blame__like_git(git_blame *blame, uint32_t opt)
origin_decref(suspect);
}
coalesce(blame);
if (!error)
coalesce(blame);
return 0;
return error;
}
void git_blame__free_entry(git_blame__entry *ent)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment