From f69e743d97cdb3f6647ea0620a22311e7bf36051 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 30 Oct 2006 17:17:41 -0800 Subject: [PATCH] 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 --- builtin-pickaxe.c | 68 ++++++++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 25 deletions(-) diff --git a/builtin-pickaxe.c b/builtin-pickaxe.c index 82868328a..32dc3932e 100644 --- a/builtin-pickaxe.c +++ b/builtin-pickaxe.c @@ -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; -- 2.30.2