/* * We are looking at the origin 'target' and aiming to pass blame * for the lines it is suspected to its parent. Run diff to find * which lines came from parent and pass blame for them. */ static void pass_blame_to_parent(struct blame_scoreboard *sb, struct blame_origin *target, struct blame_origin *parent) { mmfile_t file_p, file_o; struct blame_chunk_cb_data d; struct blame_entry *newdest = NULL; if (!target->suspects) return; /* nothing remains for this target */ d.parent = parent; d.offset = 0; d.dstq = &newdest; d.srcq = &target->suspects; fill_origin_blob(&sb->revs->diffopt, parent, &file_p, &sb->num_read_blob); fill_origin_blob(&sb->revs->diffopt, target, &file_o, &sb->num_read_blob); sb->num_get_patch++; if (diff_hunks(&file_p, &file_o, blame_chunk_cb, &d, sb->xdl_opts)) die("unable to generate diff (%s -> %s)", oid_to_hex(&parent->commit->object.oid), oid_to_hex(&target->commit->object.oid)); /* The rest are the same as the parent */ blame_chunk(&d.dstq, &d.srcq, INT_MAX, d.offset, INT_MAX, parent); *d.dstq = NULL; queue_blames(sb, parent, newdest); return; }
/* Distribute collected unsorted blames to the respected sorted lists * in the various origins. */ static void distribute_blame(struct blame_scoreboard *sb, struct blame_entry *blamed) { blamed = llist_mergesort(blamed, get_next_blame, set_next_blame, compare_blame_suspect); while (blamed) { struct blame_origin *porigin = blamed->suspect; struct blame_entry *suspects = NULL; do { struct blame_entry *next = blamed->next; blamed->next = suspects; suspects = blamed; blamed = next; } while (blamed && blamed->suspect == porigin); suspects = reverse_blame(suspects, NULL); queue_blames(sb, porigin, suspects); } }
/* * The blobs of origin and porigin exactly match, so everything * origin is suspected for can be blamed on the parent. */ static void pass_whole_blame(struct blame_scoreboard *sb, struct blame_origin *origin, struct blame_origin *porigin) { struct blame_entry *e, *suspects; if (!porigin->file.ptr && origin->file.ptr) { /* Steal its file */ porigin->file = origin->file; origin->file.ptr = NULL; } suspects = origin->suspects; origin->suspects = NULL; for (e = suspects; e; e = e->next) { blame_origin_incref(porigin); blame_origin_decref(e->suspect); e->suspect = porigin; } queue_blames(sb, porigin, suspects); }