+static void copy_split_if_better(struct blame_entry best_so_far[3],
+ struct blame_entry this[3])
+{
+ if (!this[1].suspect)
+ return;
+ if (best_so_far[1].suspect &&
+ (this[1].num_lines < best_so_far[1].num_lines))
+ return;
+ memcpy(best_so_far, this, sizeof(struct blame_entry [3]));
+}
+
+static void find_copy_in_blob(struct scoreboard *sb,
+ struct blame_entry *ent,
+ struct origin *parent,
+ struct blame_entry split[3],
+ mmfile_t *file_p)
+{
+ const char *cp;
+ int cnt;
+ mmfile_t file_o;
+ struct patch *patch;
+ int i, plno, tlno;
+
+ cp = nth_line(sb, ent->lno);
+ file_o.ptr = (char*) cp;
+ cnt = ent->num_lines;
+
+ while (cnt && cp < sb->final_buf + sb->final_buf_size) {
+ if (*cp++ == '\n')
+ cnt--;
+ }
+ file_o.size = cp - file_o.ptr;
+
+ patch = compare_buffer(file_p, &file_o, 1);
+
+ memset(split, 0, sizeof(struct blame_entry [3]));
+ plno = tlno = 0;
+ for (i = 0; i < patch->num; i++) {
+ struct chunk *chunk = &patch->chunks[i];
+
+ /* tlno to chunk->same are the same as ent */
+ if (ent->num_lines <= tlno)
+ break;
+ if (tlno < chunk->same) {
+ struct blame_entry this[3];
+ split_overlap(this, ent,
+ tlno + ent->s_lno, plno,
+ chunk->same + ent->s_lno,
+ parent);
+ copy_split_if_better(split, this);
+ }
+ plno = chunk->p_next;
+ tlno = chunk->t_next;
+ }
+ free_patch(patch);
+}
+
+static int find_move_in_parent(struct scoreboard *sb,
+ struct origin *target,
+ struct origin *parent)
+{
+ int last_in_target;
+ struct blame_entry *ent, split[3];
+ mmfile_t file_p;
+ char type[10];
+ char *blob_p;
+
+ last_in_target = find_last_in_target(sb, target);
+ if (last_in_target < 0)
+ return 1; /* nothing remains for this target */
+
+ blob_p = read_sha1_file(parent->blob_sha1, type,
+ (unsigned long *) &file_p.size);
+ file_p.ptr = blob_p;
+ if (!file_p.ptr) {
+ free(blob_p);
+ return 0;
+ }
+
+ for (ent = sb->ent; ent; ent = ent->next) {
+ if (ent->suspect != target || ent->guilty)
+ continue;
+ find_copy_in_blob(sb, ent, parent, split, &file_p);
+ if (split[1].suspect)
+ split_blame(sb, split, ent);
+ }
+ free(blob_p);
+ return 0;
+}
+