{
struct origin *porigin = NULL;
struct diff_options diff_opts;
- int i;
const char *paths[2];
/* See if the origin->path is different between parent
}
}
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;
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;