/* * 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; }
/* diff chunks are from parent to target */ static int blame_chunk_cb(long start_a, long count_a, long start_b, long count_b, void *data) { struct blame_chunk_cb_data *d = data; if (start_a - start_b != d->offset) die("internal error in blame::blame_chunk_cb"); blame_chunk(&d->dstq, &d->srcq, start_b, start_a - start_b, start_b + count_b, d->parent); d->offset = start_a + count_a - (start_b + count_b); return 0; }
static int my_emit( long start_a, long count_a, long start_b, long count_b, void *cb_data) { blame_chunk_cb_data *d = (blame_chunk_cb_data *)cb_data; blame_chunk(d->blame, d->tlno, d->plno, start_b, d->target, d->parent); d->plno = start_a + count_a; d->tlno = start_b + count_b; return 0; }
static int my_emit( xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, xdemitconf_t const *xecfg) { xdchange_t *xch = xscr; GIT_UNUSED(xe); GIT_UNUSED(xecfg); while (xch) { blame_chunk_cb_data *d = (blame_chunk_cb_data *) ecb->priv; blame_chunk(d->blame, d->tlno, d->plno, xch->i2, d->target, d->parent); d->plno = xch->i1 + xch->chg1; d->tlno = xch->i2 + xch->chg2; xch = xch->next; } return 0; }
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; }