/* * The commit page, which shows one commit on its own and is where the log and * the ref listings link. It renders the idents, the object ids, the message * and any note, then hands off to ui-diff.c for the diff against the first * parent. Free text and addresses are written through the repository's commit * and email filters, so a site can rewrite either on the way out. */ #define USE_THE_REPOSITORY_VARIABLE #include "cgit.h" #include "filter.h" #include "html.h" #include "parsing.h" #include "shared.h" #include "ui-commit.h" #include "ui-diff.h" #include "ui-log.h" #include "ui-shared.h" // The diff below the message is always taken against the first parent alone, // which says little about a merge of many branches, so a commit with this // many parents or more is shown without a diff at all. #define OCTOPUS_PARENTS 3 static void print_ident_row(const char *role, const char *name, const char *email, timestamp_t date, int tz) { htmlf("%s", role); cgit_open_filter(ctx.repo->email_filter, email, "commit"); html_txt(name); if (!ctx.cfg.noplainemail) { html(" "); html_txt(email); } cgit_close_filter(ctx.repo->email_filter); html("\n"); } static int print_parent_rows(struct commit *commit, const char *rev, const char *prefix) { struct commit_list *p; struct commit *parent; const char *parent_hex, *label; int parents = 0; for (p = commit->parents; p; p = p->next) { parent = lookup_commit_reference(the_repository, &p->item->object.oid); if (!parent) { html(""); cgit_print_error("Error reading parent commit"); html("\n"); continue; } html("parent" ""); parent_hex = label = oid_to_hex(&p->item->object.oid); if (ctx.repo->enable_subject_links) label = cgit_parse_commit(parent)->subject; cgit_commit_link(label, NULL, NULL, ctx.qry.head, parent_hex, prefix); html(" ("); cgit_diff_link("diff", NULL, NULL, ctx.qry.head, rev, oid_to_hex(&p->item->object.oid), prefix); html(")\n"); parents++; } return parents; } static void print_filtered_text(const char *text) { cgit_open_filter(ctx.repo->commit_filter); html_txt(text); cgit_close_filter(ctx.repo->commit_filter); } void cgit_print_commit(char *hex, const char *prefix) { struct commit *commit; struct commitinfo *info; struct strbuf notes = STRBUF_INIT; struct object_id oid; const char *commit_hex, *first_parent; char *tree_rev; int parents; if (!hex) hex = ctx.qry.head; if (repo_get_oid(the_repository, hex, &oid)) { cgit_print_error_page(400, "Bad request", "Bad object id: %s", hex); return; } commit = lookup_commit_reference(the_repository, &oid); if (!commit) { cgit_print_error_page(404, "Not found", "Bad commit reference: %s", hex); return; } info = cgit_parse_commit(commit); format_display_notes(&oid, ¬es, PAGE_ENCODING, 1); load_ref_decorations(NULL, DECORATE_FULL_REFS); ctx.page.title = cgit_fmtalloc("%s - %s", info->subject, ctx.page.title); cgit_print_layout_start(); cgit_print_diff_ctrls(); html("\n"); print_ident_row("author", info->author, info->author_email, info->author_date, info->author_tz); print_ident_row("committer", info->committer, info->committer_email, info->committer_date, info->committer_tz); html("\n"); // The parent rows follow the commit row so the commit hashes sit // together, leaving the tree beside the download links. parents = print_parent_rows(commit, hex, prefix); html("\n"); if (ctx.repo->snapshots) { html("\n"); } html("
commit"); commit_hex = oid_to_hex(&commit->object.oid); cgit_commit_link(commit_hex, NULL, NULL, ctx.qry.head, commit_hex, prefix); html(" ("); cgit_patch_link("patch", NULL, NULL, NULL, commit_hex, prefix); html(")
tree"); tree_rev = xstrdup(hex); cgit_tree_link(oid_to_hex(get_commit_tree_oid(commit)), NULL, NULL, ctx.qry.head, tree_rev, NULL); if (prefix) { html(" /"); cgit_tree_link(prefix, NULL, NULL, ctx.qry.head, tree_rev, prefix); } free(tree_rev); html("
download"); cgit_print_snapshot_links(ctx.repo, hex, "
"); html("
\n"); html("
"); print_filtered_text(info->subject); cgit_print_commit_decorations(commit); html("
\n"); html("
"); print_filtered_text(info->msg); html("
\n"); if (notes.len != 0) { html("
Notes
\n"); html("
"); print_filtered_text(notes.buf); html("
\n"); html("\n"); } if (parents < OCTOPUS_PARENTS) { if (parents) first_parent = oid_to_hex(&commit->parents->item->object.oid); else first_parent = NULL; cgit_print_diff(ctx.qry.oid, first_parent, prefix, 0, 0); } strbuf_release(¬es); cgit_free_commitinfo(info); cgit_print_layout_end(); }