git-pickaxe: split find_origin() into find_rename() and find_origin().

When a merge adds a new file from the second parent, the
earlier code tried to find renames in the first parent before
noticing that the vertion from the second parent was added
without modification.

Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
Junio C Hamano 2006-10-30 17:17:41 -08:00
Родитель ae86ad6575
Коммит f69e743d97
1 изменённых файлов: 43 добавлений и 25 удалений

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

@ -211,7 +211,6 @@ static struct origin *find_origin(struct scoreboard *sb,
{
struct origin *porigin = NULL;
struct diff_options diff_opts;
int i;
const char *paths[2];
/* See if the origin->path is different between parent
@ -260,10 +259,17 @@ static struct origin *find_origin(struct scoreboard *sb,
}
}
diff_flush(&diff_opts);
if (porigin)
return porigin;
return porigin;
}
/* Otherwise we would look for a rename */
static struct origin *find_rename(struct scoreboard *sb,
struct commit *parent,
struct origin *origin)
{
struct origin *porigin = NULL;
struct diff_options diff_opts;
int i;
const char *paths[2];
diff_setup(&diff_opts);
diff_opts.recursive = 1;
@ -875,34 +881,46 @@ static int find_copy_in_parent(struct scoreboard *sb,
static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
{
int i;
int i, pass;
struct commit *commit = origin->commit;
struct commit_list *parent;
struct origin *parent_origin[MAXPARENT], *porigin;
memset(parent_origin, 0, sizeof(parent_origin));
for (i = 0, parent = commit->parents;
i < MAXPARENT && parent;
parent = parent->next, i++) {
struct commit *p = parent->item;
if (parse_commit(p))
continue;
porigin = find_origin(sb, parent->item, origin);
if (!porigin)
continue;
if (!hashcmp(porigin->blob_sha1, origin->blob_sha1)) {
struct blame_entry *e;
for (e = sb->ent; e; e = e->next)
if (e->suspect == origin) {
origin_incref(porigin);
origin_decref(e->suspect);
e->suspect = porigin;
}
origin_decref(porigin);
goto finish;
/* The first pass looks for unrenamed path to optimize for
* common cases, then we look for renames in the second pass.
*/
for (pass = 0; pass < 2; pass++) {
struct origin *(*find)(struct scoreboard *,
struct commit *, struct origin *);
find = pass ? find_rename : find_origin;
for (i = 0, parent = commit->parents;
i < MAXPARENT && parent;
parent = parent->next, i++) {
struct commit *p = parent->item;
if (parent_origin[i])
continue;
if (parse_commit(p))
continue;
porigin = find(sb, parent->item, origin);
if (!porigin)
continue;
if (!hashcmp(porigin->blob_sha1, origin->blob_sha1)) {
struct blame_entry *e;
for (e = sb->ent; e; e = e->next)
if (e->suspect == origin) {
origin_incref(porigin);
origin_decref(e->suspect);
e->suspect = porigin;
}
origin_decref(porigin);
goto finish;
}
parent_origin[i] = porigin;
}
parent_origin[i] = porigin;
}
for (i = 0, parent = commit->parents;