+static int find_copy_in_parent(struct scoreboard *sb,
+ struct origin *target,
+ struct commit *parent,
+ struct origin *porigin,
+ int opt)
+{
+ struct diff_options diff_opts;
+ const char *paths[1];
+ struct blame_entry *ent;
+ int i;
+
+ if (find_last_in_target(sb, target) < 0)
+ return 1; /* nothing remains for this target */
+
+ diff_setup(&diff_opts);
+ diff_opts.recursive = 1;
+ diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT;
+
+ /* Try "find copies harder" on new path */
+ if ((opt & PICKAXE_BLAME_COPY_HARDER) &&
+ (!porigin || strcmp(target->path, porigin->path))) {
+ diff_opts.detect_rename = DIFF_DETECT_COPY;
+ diff_opts.find_copies_harder = 1;
+ }
+ paths[0] = NULL;
+ diff_tree_setup_paths(paths, &diff_opts);
+ if (diff_setup_done(&diff_opts) < 0)
+ die("diff-setup");
+ diff_tree_sha1(parent->tree->object.sha1,
+ target->commit->tree->object.sha1,
+ "", &diff_opts);
+ diffcore_std(&diff_opts);
+
+ for (ent = sb->ent; ent; ent = ent->next) {
+ struct blame_entry split[3];
+ if (ent->suspect != target || ent->guilty)
+ continue;
+
+ memset(split, 0, sizeof(split));
+ for (i = 0; i < diff_queued_diff.nr; i++) {
+ struct diff_filepair *p = diff_queued_diff.queue[i];
+ struct origin *norigin;
+ mmfile_t file_p;
+ char type[10];
+ char *blob;
+ struct blame_entry this[3];
+
+ if (!DIFF_FILE_VALID(p->one))
+ continue; /* does not exist in parent */
+ if (porigin && !strcmp(p->one->path, porigin->path))
+ /* find_move already dealt with this path */
+ continue;
+ norigin = find_origin(sb, parent, p->one->path);
+
+ blob = read_sha1_file(norigin->blob_sha1, type,
+ (unsigned long *) &file_p.size);
+ file_p.ptr = blob;
+ if (!file_p.ptr) {
+ free(blob);
+ continue;
+ }
+ find_copy_in_blob(sb, ent, norigin, this, &file_p);
+ copy_split_if_better(split, this);
+ }
+ if (split[1].suspect)
+ split_blame(sb, split, ent);
+ }
+ diff_flush(&diff_opts);
+
+ return 0;
+}
+