static int format_reflog_person(struct strbuf *sb, char part, struct reflog_walk_info *log, enum date_mode dmode) { const char *ident; if (!log) return 2; ident = get_reflog_ident(log); if (!ident) return 2; return format_person_part(sb, part, ident, strlen(ident), dmode); }
static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */ const char *placeholder, void *context) { struct format_commit_context *c = context; const struct commit *commit = c->commit; const char *msg = c->message; struct commit_list *p; int h1, h2; /* these are independent of the commit */ switch (placeholder[0]) { case 'C': if (starts_with(placeholder + 1, "(auto)")) { c->auto_color = 1; return 7; /* consumed 7 bytes, "C(auto)" */ } else { int ret = parse_color(sb, placeholder, c); if (ret) c->auto_color = 0; /* * Otherwise, we decided to treat %C<unknown> * as a literal string, and the previous * %C(auto) is still valid. */ return ret; } case 'n': /* newline */ strbuf_addch(sb, '\n'); return 1; case 'x': /* %x00 == NUL, %x0a == LF, etc. */ if (0 <= (h1 = hexval_table[0xff & placeholder[1]]) && h1 <= 16 && 0 <= (h2 = hexval_table[0xff & placeholder[2]]) && h2 <= 16) { strbuf_addch(sb, (h1<<4)|h2); return 3; } else return 0; case 'w': if (placeholder[1] == '(') { unsigned long width = 0, indent1 = 0, indent2 = 0; char *next; const char *start = placeholder + 2; const char *end = strchr(start, ')'); if (!end) return 0; if (end > start) { width = strtoul(start, &next, 10); if (*next == ',') { indent1 = strtoul(next + 1, &next, 10); if (*next == ',') { indent2 = strtoul(next + 1, &next, 10); } } if (*next != ')') return 0; } rewrap_message_tail(sb, c, width, indent1, indent2); return end - placeholder + 1; } else return 0; case '<': case '>': return parse_padding_placeholder(sb, placeholder, c); } /* these depend on the commit */ if (!commit->object.parsed) parse_object(commit->object.sha1); switch (placeholder[0]) { case 'H': /* commit hash */ strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT)); strbuf_addstr(sb, sha1_to_hex(commit->object.sha1)); strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET)); return 1; case 'h': /* abbreviated commit hash */ strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT)); if (add_again(sb, &c->abbrev_commit_hash)) { strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET)); return 1; } strbuf_addstr(sb, find_unique_abbrev(commit->object.sha1, c->pretty_ctx->abbrev)); strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET)); c->abbrev_commit_hash.len = sb->len - c->abbrev_commit_hash.off; return 1; case 'T': /* tree hash */ strbuf_addstr(sb, sha1_to_hex(commit->tree->object.sha1)); return 1; case 't': /* abbreviated tree hash */ if (add_again(sb, &c->abbrev_tree_hash)) return 1; strbuf_addstr(sb, find_unique_abbrev(commit->tree->object.sha1, c->pretty_ctx->abbrev)); c->abbrev_tree_hash.len = sb->len - c->abbrev_tree_hash.off; return 1; case 'P': /* parent hashes */ for (p = commit->parents; p; p = p->next) { if (p != commit->parents) strbuf_addch(sb, ' '); strbuf_addstr(sb, sha1_to_hex(p->item->object.sha1)); } return 1; case 'p': /* abbreviated parent hashes */ if (add_again(sb, &c->abbrev_parent_hashes)) return 1; for (p = commit->parents; p; p = p->next) { if (p != commit->parents) strbuf_addch(sb, ' '); strbuf_addstr(sb, find_unique_abbrev( p->item->object.sha1, c->pretty_ctx->abbrev)); } c->abbrev_parent_hashes.len = sb->len - c->abbrev_parent_hashes.off; return 1; case 'm': /* left/right/bottom */ strbuf_addstr(sb, get_revision_mark(NULL, commit)); return 1; case 'd': load_ref_decorations(DECORATE_SHORT_REFS); format_decorations(sb, commit, c->auto_color); return 1; case 'g': /* reflog info */ switch(placeholder[1]) { case 'd': /* reflog selector */ case 'D': if (c->pretty_ctx->reflog_info) get_reflog_selector(sb, c->pretty_ctx->reflog_info, c->pretty_ctx->date_mode, c->pretty_ctx->date_mode_explicit, (placeholder[1] == 'd')); return 2; case 's': /* reflog message */ if (c->pretty_ctx->reflog_info) get_reflog_message(sb, c->pretty_ctx->reflog_info); return 2; case 'n': case 'N': case 'e': case 'E': return format_reflog_person(sb, placeholder[1], c->pretty_ctx->reflog_info, c->pretty_ctx->date_mode); } return 0; /* unknown %g placeholder */ case 'N': if (c->pretty_ctx->notes_message) { strbuf_addstr(sb, c->pretty_ctx->notes_message); return 1; } return 0; } if (placeholder[0] == 'G') { if (!c->signature_check.result) check_commit_signature(c->commit, &(c->signature_check)); switch (placeholder[1]) { case 'G': if (c->signature_check.gpg_output) strbuf_addstr(sb, c->signature_check.gpg_output); break; case '?': switch (c->signature_check.result) { case 'G': case 'B': case 'U': case 'N': strbuf_addch(sb, c->signature_check.result); } break; case 'S': if (c->signature_check.signer) strbuf_addstr(sb, c->signature_check.signer); break; case 'K': if (c->signature_check.key) strbuf_addstr(sb, c->signature_check.key); break; default: return 0; } return 2; } /* For the rest we have to parse the commit header. */ if (!c->commit_header_parsed) parse_commit_header(c); switch (placeholder[0]) { case 'a': /* author ... */ return format_person_part(sb, placeholder[1], msg + c->author.off, c->author.len, c->pretty_ctx->date_mode); case 'c': /* committer ... */ return format_person_part(sb, placeholder[1], msg + c->committer.off, c->committer.len, c->pretty_ctx->date_mode); case 'e': /* encoding */ if (c->commit_encoding) strbuf_addstr(sb, c->commit_encoding); return 1; case 'B': /* raw body */ /* message_off is always left at the initial newline */ strbuf_addstr(sb, msg + c->message_off + 1); return 1; } /* Now we need to parse the commit message. */ if (!c->commit_message_parsed) parse_commit_message(c); switch (placeholder[0]) { case 's': /* subject */ format_subject(sb, msg + c->subject_off, " "); return 1; case 'f': /* sanitized subject */ format_sanitized_subject(sb, msg + c->subject_off); return 1; case 'b': /* body */ strbuf_addstr(sb, msg + c->body_off); return 1; } return 0; /* unknown placeholder */ }
static size_t format_commit_item(struct strbuf *sb, const char *placeholder, void *context) { struct format_commit_context *c = context; const struct commit *commit = c->commit; const char *msg = commit->buffer; struct commit_list *p; int h1, h2; /* these are independent of the commit */ switch (placeholder[0]) { case 'C': if (!prefixcmp(placeholder + 1, "red")) { strbuf_addstr(sb, "\033[31m"); return 4; } else if (!prefixcmp(placeholder + 1, "green")) { strbuf_addstr(sb, "\033[32m"); return 6; } else if (!prefixcmp(placeholder + 1, "blue")) { strbuf_addstr(sb, "\033[34m"); return 5; } else if (!prefixcmp(placeholder + 1, "reset")) { strbuf_addstr(sb, "\033[m"); return 6; } else return 0; case 'n': /* newline */ strbuf_addch(sb, '\n'); return 1; case 'x': /* %x00 == NUL, %x0a == LF, etc. */ if (0 <= (h1 = hexval_table[0xff & placeholder[1]]) && h1 <= 16 && 0 <= (h2 = hexval_table[0xff & placeholder[2]]) && h2 <= 16) { strbuf_addch(sb, (h1<<4)|h2); return 3; } else return 0; } /* these depend on the commit */ if (!commit->object.parsed) parse_object(commit->object.sha1); switch (placeholder[0]) { case 'H': /* commit hash */ strbuf_addstr(sb, sha1_to_hex(commit->object.sha1)); return 1; case 'h': /* abbreviated commit hash */ if (add_again(sb, &c->abbrev_commit_hash)) return 1; strbuf_addstr(sb, find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV)); c->abbrev_commit_hash.len = sb->len - c->abbrev_commit_hash.off; return 1; case 'T': /* tree hash */ strbuf_addstr(sb, sha1_to_hex(commit->tree->object.sha1)); return 1; case 't': /* abbreviated tree hash */ if (add_again(sb, &c->abbrev_tree_hash)) return 1; strbuf_addstr(sb, find_unique_abbrev(commit->tree->object.sha1, DEFAULT_ABBREV)); c->abbrev_tree_hash.len = sb->len - c->abbrev_tree_hash.off; return 1; case 'P': /* parent hashes */ for (p = commit->parents; p; p = p->next) { if (p != commit->parents) strbuf_addch(sb, ' '); strbuf_addstr(sb, sha1_to_hex(p->item->object.sha1)); } return 1; case 'p': /* abbreviated parent hashes */ if (add_again(sb, &c->abbrev_parent_hashes)) return 1; for (p = commit->parents; p; p = p->next) { if (p != commit->parents) strbuf_addch(sb, ' '); strbuf_addstr(sb, find_unique_abbrev( p->item->object.sha1, DEFAULT_ABBREV)); } c->abbrev_parent_hashes.len = sb->len - c->abbrev_parent_hashes.off; return 1; case 'm': /* left/right/bottom */ strbuf_addch(sb, (commit->object.flags & BOUNDARY) ? '-' : (commit->object.flags & SYMMETRIC_LEFT) ? '<' : '>'); return 1; } /* For the rest we have to parse the commit header. */ if (!c->commit_header_parsed) parse_commit_header(c); switch (placeholder[0]) { case 's': /* subject */ strbuf_add(sb, msg + c->subject.off, c->subject.len); return 1; case 'a': /* author ... */ return format_person_part(sb, placeholder[1], msg + c->author.off, c->author.len); case 'c': /* committer ... */ return format_person_part(sb, placeholder[1], msg + c->committer.off, c->committer.len); case 'e': /* encoding */ strbuf_add(sb, msg + c->encoding.off, c->encoding.len); return 1; case 'b': /* body */ strbuf_addstr(sb, msg + c->body_off); return 1; } return 0; /* unknown placeholder */ }
static size_t format_commit_one(struct strbuf *sb, const char *placeholder, void *context) { struct format_commit_context *c = context; const struct commit *commit = c->commit; const char *msg = commit->buffer; struct commit_list *p; int h1, h2; /* these are independent of the commit */ switch (placeholder[0]) { case 'C': if (placeholder[1] == '(') { const char *end = strchr(placeholder + 2, ')'); char color[COLOR_MAXLEN]; if (!end) return 0; color_parse_mem(placeholder + 2, end - (placeholder + 2), "--pretty format", color); strbuf_addstr(sb, color); return end - placeholder + 1; } if (!prefixcmp(placeholder + 1, "red")) { strbuf_addstr(sb, GIT_COLOR_RED); return 4; } else if (!prefixcmp(placeholder + 1, "green")) { strbuf_addstr(sb, GIT_COLOR_GREEN); return 6; } else if (!prefixcmp(placeholder + 1, "blue")) { strbuf_addstr(sb, GIT_COLOR_BLUE); return 5; } else if (!prefixcmp(placeholder + 1, "reset")) { strbuf_addstr(sb, GIT_COLOR_RESET); return 6; } else return 0; case 'n': /* newline */ strbuf_addch(sb, '\n'); return 1; case 'x': /* %x00 == NUL, %x0a == LF, etc. */ if (0 <= (h1 = hexval_table[0xff & placeholder[1]]) && h1 <= 16 && 0 <= (h2 = hexval_table[0xff & placeholder[2]]) && h2 <= 16) { strbuf_addch(sb, (h1<<4)|h2); return 3; } else return 0; case 'w': if (placeholder[1] == '(') { unsigned long width = 0, indent1 = 0, indent2 = 0; char *next; const char *start = placeholder + 2; const char *end = strchr(start, ')'); if (!end) return 0; if (end > start) { width = strtoul(start, &next, 10); if (*next == ',') { indent1 = strtoul(next + 1, &next, 10); if (*next == ',') { indent2 = strtoul(next + 1, &next, 10); } } if (*next != ')') return 0; } rewrap_message_tail(sb, c, width, indent1, indent2); return end - placeholder + 1; } else return 0; } /* these depend on the commit */ if (!commit->object.parsed) parse_object(commit->object.sha1); switch (placeholder[0]) { case 'H': /* commit hash */ strbuf_addstr(sb, sha1_to_hex(commit->object.sha1)); return 1; case 'h': /* abbreviated commit hash */ if (add_again(sb, &c->abbrev_commit_hash)) return 1; strbuf_addstr(sb, find_unique_abbrev(commit->object.sha1, c->pretty_ctx->abbrev)); c->abbrev_commit_hash.len = sb->len - c->abbrev_commit_hash.off; return 1; case 'T': /* tree hash */ strbuf_addstr(sb, sha1_to_hex(commit->tree->object.sha1)); return 1; case 't': /* abbreviated tree hash */ if (add_again(sb, &c->abbrev_tree_hash)) return 1; strbuf_addstr(sb, find_unique_abbrev(commit->tree->object.sha1, c->pretty_ctx->abbrev)); c->abbrev_tree_hash.len = sb->len - c->abbrev_tree_hash.off; return 1; case 'P': /* parent hashes */ for (p = commit->parents; p; p = p->next) { if (p != commit->parents) strbuf_addch(sb, ' '); strbuf_addstr(sb, sha1_to_hex(p->item->object.sha1)); } return 1; case 'p': /* abbreviated parent hashes */ if (add_again(sb, &c->abbrev_parent_hashes)) return 1; for (p = commit->parents; p; p = p->next) { if (p != commit->parents) strbuf_addch(sb, ' '); strbuf_addstr(sb, find_unique_abbrev( p->item->object.sha1, c->pretty_ctx->abbrev)); } c->abbrev_parent_hashes.len = sb->len - c->abbrev_parent_hashes.off; return 1; case 'm': /* left/right/bottom */ strbuf_addch(sb, (commit->object.flags & BOUNDARY) ? '-' : (commit->object.flags & SYMMETRIC_LEFT) ? '<' : '>'); return 1; case 'd': format_decoration(sb, commit); return 1; case 'g': /* reflog info */ switch(placeholder[1]) { case 'd': /* reflog selector */ case 'D': if (c->pretty_ctx->reflog_info) get_reflog_selector(sb, c->pretty_ctx->reflog_info, c->pretty_ctx->date_mode, (placeholder[1] == 'd')); return 2; case 's': /* reflog message */ if (c->pretty_ctx->reflog_info) get_reflog_message(sb, c->pretty_ctx->reflog_info); return 2; } return 0; /* unknown %g placeholder */ case 'N': if (c->pretty_ctx->show_notes) { format_display_notes(commit->object.sha1, sb, git_log_output_encoding ? git_log_output_encoding : git_commit_encoding, 0); return 1; } return 0; } /* For the rest we have to parse the commit header. */ if (!c->commit_header_parsed) parse_commit_header(c); switch (placeholder[0]) { case 'a': /* author ... */ return format_person_part(sb, placeholder[1], msg + c->author.off, c->author.len, c->pretty_ctx->date_mode); case 'c': /* committer ... */ return format_person_part(sb, placeholder[1], msg + c->committer.off, c->committer.len, c->pretty_ctx->date_mode); case 'e': /* encoding */ strbuf_add(sb, msg + c->encoding.off, c->encoding.len); return 1; case 'B': /* raw body */ /* message_off is always left at the initial newline */ strbuf_addstr(sb, msg + c->message_off + 1); return 1; } /* Now we need to parse the commit message. */ if (!c->commit_message_parsed) parse_commit_message(c); switch (placeholder[0]) { case 's': /* subject */ format_subject(sb, msg + c->subject_off, " "); return 1; case 'f': /* sanitized subject */ format_sanitized_subject(sb, msg + c->subject_off); return 1; case 'b': /* body */ strbuf_addstr(sb, msg + c->body_off); return 1; } return 0; /* unknown placeholder */ }
static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */ const char *placeholder, void *context) { struct format_commit_context *c = context; const struct commit *commit = c->commit; const char *msg = c->message; struct commit_list *p; const char *arg; int ch; /* these are independent of the commit */ switch (placeholder[0]) { case 'C': if (starts_with(placeholder + 1, "(auto)")) { c->auto_color = want_color(c->pretty_ctx->color); if (c->auto_color && sb->len) strbuf_addstr(sb, GIT_COLOR_RESET); return 7; /* consumed 7 bytes, "C(auto)" */ } else { int ret = parse_color(sb, placeholder, c); if (ret) c->auto_color = 0; /* * Otherwise, we decided to treat %C<unknown> * as a literal string, and the previous * %C(auto) is still valid. */ return ret; } case 'n': /* newline */ strbuf_addch(sb, '\n'); return 1; case 'x': /* %x00 == NUL, %x0a == LF, etc. */ ch = hex2chr(placeholder + 1); if (ch < 0) return 0; strbuf_addch(sb, ch); return 3; case 'w': if (placeholder[1] == '(') { unsigned long width = 0, indent1 = 0, indent2 = 0; char *next; const char *start = placeholder + 2; const char *end = strchr(start, ')'); if (!end) return 0; if (end > start) { width = strtoul(start, &next, 10); if (*next == ',') { indent1 = strtoul(next + 1, &next, 10); if (*next == ',') { indent2 = strtoul(next + 1, &next, 10); } } if (*next != ')') return 0; } rewrap_message_tail(sb, c, width, indent1, indent2); return end - placeholder + 1; } else return 0; case '<': case '>': return parse_padding_placeholder(sb, placeholder, c); } /* these depend on the commit */ if (!commit->object.parsed) parse_object(&commit->object.oid); switch (placeholder[0]) { case 'H': /* commit hash */ strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT)); strbuf_addstr(sb, oid_to_hex(&commit->object.oid)); strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET)); return 1; case 'h': /* abbreviated commit hash */ strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_COMMIT)); strbuf_add_unique_abbrev(sb, &commit->object.oid, c->pretty_ctx->abbrev); strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET)); return 1; case 'T': /* tree hash */ strbuf_addstr(sb, oid_to_hex(get_commit_tree_oid(commit))); return 1; case 't': /* abbreviated tree hash */ strbuf_add_unique_abbrev(sb, get_commit_tree_oid(commit), c->pretty_ctx->abbrev); return 1; case 'P': /* parent hashes */ for (p = commit->parents; p; p = p->next) { if (p != commit->parents) strbuf_addch(sb, ' '); strbuf_addstr(sb, oid_to_hex(&p->item->object.oid)); } return 1; case 'p': /* abbreviated parent hashes */ for (p = commit->parents; p; p = p->next) { if (p != commit->parents) strbuf_addch(sb, ' '); strbuf_add_unique_abbrev(sb, &p->item->object.oid, c->pretty_ctx->abbrev); } return 1; case 'm': /* left/right/bottom */ strbuf_addstr(sb, get_revision_mark(NULL, commit)); return 1; case 'd': load_ref_decorations(NULL, DECORATE_SHORT_REFS); format_decorations(sb, commit, c->auto_color); return 1; case 'D': load_ref_decorations(NULL, DECORATE_SHORT_REFS); format_decorations_extended(sb, commit, c->auto_color, "", ", ", ""); return 1; case 'g': /* reflog info */ switch(placeholder[1]) { case 'd': /* reflog selector */ case 'D': if (c->pretty_ctx->reflog_info) get_reflog_selector(sb, c->pretty_ctx->reflog_info, &c->pretty_ctx->date_mode, c->pretty_ctx->date_mode_explicit, (placeholder[1] == 'd')); return 2; case 's': /* reflog message */ if (c->pretty_ctx->reflog_info) get_reflog_message(sb, c->pretty_ctx->reflog_info); return 2; case 'n': case 'N': case 'e': case 'E': return format_reflog_person(sb, placeholder[1], c->pretty_ctx->reflog_info, &c->pretty_ctx->date_mode); } return 0; /* unknown %g placeholder */ case 'N': if (c->pretty_ctx->notes_message) { strbuf_addstr(sb, c->pretty_ctx->notes_message); return 1; } return 0; } if (placeholder[0] == 'G') { if (!c->signature_check.result) check_commit_signature(c->commit, &(c->signature_check)); switch (placeholder[1]) { case 'G': if (c->signature_check.gpg_output) strbuf_addstr(sb, c->signature_check.gpg_output); break; case '?': switch (c->signature_check.result) { case 'G': case 'B': case 'E': case 'U': case 'N': case 'X': case 'Y': case 'R': strbuf_addch(sb, c->signature_check.result); } break; case 'S': if (c->signature_check.signer) strbuf_addstr(sb, c->signature_check.signer); break; case 'K': if (c->signature_check.key) strbuf_addstr(sb, c->signature_check.key); break; default: return 0; } return 2; } /* For the rest we have to parse the commit header. */ if (!c->commit_header_parsed) parse_commit_header(c); switch (placeholder[0]) { case 'a': /* author ... */ return format_person_part(sb, placeholder[1], msg + c->author.off, c->author.len, &c->pretty_ctx->date_mode); case 'c': /* committer ... */ return format_person_part(sb, placeholder[1], msg + c->committer.off, c->committer.len, &c->pretty_ctx->date_mode); case 'e': /* encoding */ if (c->commit_encoding) strbuf_addstr(sb, c->commit_encoding); return 1; case 'B': /* raw body */ /* message_off is always left at the initial newline */ strbuf_addstr(sb, msg + c->message_off + 1); return 1; } /* Now we need to parse the commit message. */ if (!c->commit_message_parsed) parse_commit_message(c); switch (placeholder[0]) { case 's': /* subject */ format_subject(sb, msg + c->subject_off, " "); return 1; case 'f': /* sanitized subject */ format_sanitized_subject(sb, msg + c->subject_off); return 1; case 'b': /* body */ strbuf_addstr(sb, msg + c->body_off); return 1; } if (skip_prefix(placeholder, "(trailers", &arg)) { struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT; if (*arg == ':') { arg++; for (;;) { if (match_placeholder_arg(arg, "only", &arg)) opts.only_trailers = 1; else if (match_placeholder_arg(arg, "unfold", &arg)) opts.unfold = 1; else break; } } if (*arg == ')') { format_trailers_from_commit(sb, msg + c->subject_off, &opts); return arg - placeholder + 1; } } return 0; /* unknown placeholder */ }