/* * Find the lines from parent that are the same as ent so that * we can pass blames to it. file_p has the blob contents for * the parent. */ static void find_copy_in_blob(struct blame_scoreboard *sb, struct blame_entry *ent, struct blame_origin *parent, struct blame_entry *split, mmfile_t *file_p) { const char *cp; mmfile_t file_o; struct handle_split_cb_data d; memset(&d, 0, sizeof(d)); d.sb = sb; d.ent = ent; d.parent = parent; d.split = split; /* * Prepare mmfile that contains only the lines in ent. */ cp = blame_nth_line(sb, ent->lno); file_o.ptr = (char *) cp; file_o.size = blame_nth_line(sb, ent->lno + ent->num_lines) - cp; /* * file_o is a part of final image we are annotating. * file_p partially may match that image. */ memset(split, 0, sizeof(struct blame_entry [3])); if (diff_hunks(file_p, &file_o, handle_split_cb, &d, sb->xdl_opts)) die("unable to generate diff (%s)", oid_to_hex(&parent->commit->object.oid)); /* remainder, if any, all match the preimage */ handle_split(sb, ent, d.tlno, d.plno, ent->num_lines, parent, split); }
/* * 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; }
static int pass_blame_to_parent( git_blame *blame, git_blame__origin *target, git_blame__origin *parent) { int last_in_target; mmfile_t file_p, file_o; blame_chunk_cb_data d = { blame, target, parent, 0, 0 }; last_in_target = find_last_in_target(blame, target); if (last_in_target < 0) return 1; /* nothing remains for this target */ fill_origin_blob(parent, &file_p); fill_origin_blob(target, &file_o); diff_hunks(file_p, file_o, &d); /* The reset (i.e. anything after tlno) are the same as the parent */ blame_chunk(blame, d.tlno, d.plno, last_in_target, target, parent); return 0; }