/* * 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); }
/* * The lines in blame_entry after splitting blames many times can become * very small and trivial, and at some point it becomes pointless to * blame the parents. E.g. "\t\t}\n\t}\n\n" appears everywhere in any * ordinary C program, and it is not worth to say it was copied from * totally unrelated file in the parent. * * Compute how trivial the lines in the blame_entry are. */ unsigned blame_entry_score(struct blame_scoreboard *sb, struct blame_entry *e) { unsigned score; const char *cp, *ep; if (e->score) return e->score; score = 1; cp = blame_nth_line(sb, e->lno); ep = blame_nth_line(sb, e->lno + e->num_lines); while (cp < ep) { unsigned ch = *((unsigned char *)cp); if (isalnum(ch)) score++; cp++; } e->score = score; return score; }
static void emit_blame_entry_line_background(struct blame_scoreboard *sb, struct blame_entry *ent) { unsigned long line; size_t len, maxlen = 2; const char* pos, *endpos; for (line = ent->lno; line < ent->lno + ent->num_lines; line++) { html("\n"); pos = blame_nth_line(sb, line); endpos = blame_nth_line(sb, line + 1); len = 0; while (pos < endpos) { len++; if (*pos++ == '\t') len = (len + 7) & ~7; } if (len > maxlen) maxlen = len; } for (len = 0; len < maxlen - 1; len++) html(" "); }
static void emit_porcelain(struct blame_scoreboard *sb, struct blame_entry *ent, int opt) { int repeat = opt & OUTPUT_LINE_PORCELAIN; int cnt; const char *cp; struct blame_origin *suspect = ent->suspect; char hex[GIT_MAX_HEXSZ + 1]; oid_to_hex_r(hex, &suspect->commit->object.oid); printf("%s %d %d %d\n", hex, ent->s_lno + 1, ent->lno + 1, ent->num_lines); emit_porcelain_details(suspect, repeat); cp = blame_nth_line(sb, ent->lno); for (cnt = 0; cnt < ent->num_lines; cnt++) { char ch; if (cnt) { printf("%s %d %d\n", hex, ent->s_lno + 1 + cnt, ent->lno + 1 + cnt); if (repeat) emit_porcelain_details(suspect, 1); } putchar('\t'); do { ch = *cp++; putchar(ch); } while (ch != '\n' && cp < sb->final_buf + sb->final_buf_size); } if (sb->final_buf_size && cp[-1] != '\n') putchar('\n'); }
static const char *nth_line_cb(void *data, long lno) { return blame_nth_line((struct blame_scoreboard *)data, lno); }
static void emit_other(struct blame_scoreboard *sb, struct blame_entry *ent, int opt) { int cnt; const char *cp; struct blame_origin *suspect = ent->suspect; struct commit_info ci; char hex[GIT_MAX_HEXSZ + 1]; int show_raw_time = !!(opt & OUTPUT_RAW_TIMESTAMP); get_commit_info(suspect->commit, &ci, 1); oid_to_hex_r(hex, &suspect->commit->object.oid); cp = blame_nth_line(sb, ent->lno); for (cnt = 0; cnt < ent->num_lines; cnt++) { char ch; int length = (opt & OUTPUT_LONG_OBJECT_NAME) ? GIT_SHA1_HEXSZ : abbrev; if (suspect->commit->object.flags & UNINTERESTING) { if (blank_boundary) memset(hex, ' ', length); else if (!(opt & OUTPUT_ANNOTATE_COMPAT)) { length--; putchar('^'); } } printf("%.*s", length, hex); if (opt & OUTPUT_ANNOTATE_COMPAT) { const char *name; if (opt & OUTPUT_SHOW_EMAIL) name = ci.author_mail.buf; else name = ci.author.buf; printf("\t(%10s\t%10s\t%d)", name, format_time(ci.author_time, ci.author_tz.buf, show_raw_time), ent->lno + 1 + cnt); } else { if (opt & OUTPUT_SHOW_SCORE) printf(" %*d %02d", max_score_digits, ent->score, ent->suspect->refcnt); if (opt & OUTPUT_SHOW_NAME) printf(" %-*.*s", longest_file, longest_file, suspect->path); if (opt & OUTPUT_SHOW_NUMBER) printf(" %*d", max_orig_digits, ent->s_lno + 1 + cnt); if (!(opt & OUTPUT_NO_AUTHOR)) { const char *name; int pad; if (opt & OUTPUT_SHOW_EMAIL) name = ci.author_mail.buf; else name = ci.author.buf; pad = longest_author - utf8_strwidth(name); printf(" (%s%*s %10s", name, pad, "", format_time(ci.author_time, ci.author_tz.buf, show_raw_time)); } printf(" %*d) ", max_digits, ent->lno + 1 + cnt); } do { ch = *cp++; putchar(ch); } while (ch != '\n' && cp < sb->final_buf + sb->final_buf_size); } if (sb->final_buf_size && cp[-1] != '\n') putchar('\n'); commit_info_destroy(&ci); }