From 9a8d39c668b98464bac97d4e5442966de63f97b2 Mon Sep 17 00:00:00 2001 From: Johan Herland Date: Mon, 15 Nov 2010 18:39:50 +0100 Subject: ui-log: Implement support for commit graphs Teach CGit to print an ASCII art commit graph to the left of the commit message, similar to 'git log --graph'. The graph adds extra lines (table rows) to the log when needed to add/remove/shuffle edges in the graph. When 'showmsg' is enabled, the graph is automatically padded to account for the extra lines added by the commit message/notes. This feature is controlled by a new config variable: "enable-commit-graph" (disabled by default), and individual repos can control it by setting "repo.enable-commit-graph". Signed-off-by: Johan Herland Signed-off-by: Lars Hjemli --- ui-log.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 82 insertions(+), 21 deletions(-) (limited to 'ui-log.c') diff --git a/ui-log.c b/ui-log.c index 6d7fcae..0d86fd5 100644 --- a/ui-log.c +++ b/ui-log.c @@ -77,11 +77,30 @@ void show_commit_decorations(struct commit *commit) } } -void print_commit(struct commit *commit) +void print_commit(struct commit *commit, struct rev_info *revs) { struct commitinfo *info; char *tmp; int cols = 2; + struct strbuf graphbuf = STRBUF_INIT; + + if (ctx.repo->enable_log_filecount) { + cols++; + if (ctx.repo->enable_log_linecount) + cols++; + } + + if (revs->graph) { + /* Advance graph until current commit */ + while (!graph_next_line(revs->graph, &graphbuf)) { + /* Print graph segment in otherwise empty table row */ + html(""); + html(graphbuf.buf); + htmlf("\n", cols); + strbuf_setlen(&graphbuf, 0); + } + /* Current commit's graph segment is now ready in graphbuf */ + } info = cgit_parse_commit(commit); htmlf("", @@ -91,8 +110,17 @@ void print_commit(struct commit *commit) html_link_open(tmp, NULL, NULL); cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE); html_link_close(); - htmlf("", - ctx.qry.showmsg ? " class='logsubject'" : ""); + html(""); + + if (revs->graph) { + /* Print graph segment for current commit */ + html(""); + html(graphbuf.buf); + html(""); + strbuf_setlen(&graphbuf, 0); + } + + htmlf("", ctx.qry.showmsg ? " class='logsubject'" : ""); cgit_commit_link(info->subject, NULL, NULL, ctx.qry.head, sha1_to_hex(commit->object.sha1), ctx.qry.vpath, 0); show_commit_decorations(commit); @@ -112,32 +140,59 @@ void print_commit(struct commit *commit) } html("\n"); - if (ctx.qry.showmsg) { /* Print message + notes in a second table row */ - /* Concatenate commit message and notes in msgbuf */ + if (revs->graph || ctx.qry.showmsg) { /* Print a second table row */ struct strbuf msgbuf = STRBUF_INIT; - if (info->msg && *(info->msg)) { - strbuf_addstr(&msgbuf, info->msg); + html(""); /* Empty 'Age' column */ + + if (ctx.qry.showmsg) { + /* Concatenate commit message + notes in msgbuf */ + if (info->msg && *(info->msg)) { + strbuf_addstr(&msgbuf, info->msg); + strbuf_addch(&msgbuf, '\n'); + } + format_note(NULL, commit->object.sha1, &msgbuf, + PAGE_ENCODING, + NOTES_SHOW_HEADER | NOTES_INDENT); strbuf_addch(&msgbuf, '\n'); + strbuf_ltrim(&msgbuf); } - format_note(NULL, commit->object.sha1, &msgbuf, PAGE_ENCODING, - NOTES_SHOW_HEADER | NOTES_INDENT); - strbuf_addch(&msgbuf, '\n'); - strbuf_ltrim(&msgbuf); - if (ctx.repo->enable_log_filecount) { - cols++; - if (ctx.repo->enable_log_linecount) - cols++; + if (revs->graph) { + int lines = 0; + + /* Calculate graph padding */ + if (ctx.qry.showmsg) { + /* Count #lines in commit message + notes */ + const char *p = msgbuf.buf; + lines = 1; + while ((p = strchr(p, '\n'))) { + p++; + lines++; + } + } + + /* Print graph padding */ + html(""); + while (lines > 0 || !graph_is_commit_finished(revs->graph)) { + if (graphbuf.len) + html("\n"); + strbuf_setlen(&graphbuf, 0); + graph_next_line(revs->graph, &graphbuf); + html(graphbuf.buf); + lines--; + } + html("\n"); } - /* Create second table row containing msgbuf */ - htmlf("", - cols); + /* Print msgbuf into remainder of table row */ + htmlf("\n", cols, + ctx.qry.showmsg ? " class='logmsg'" : ""); html_txt(msgbuf.buf); html("\n"); strbuf_release(&msgbuf); } + strbuf_release(&graphbuf); cgit_free_commitinfo(info); } @@ -216,6 +271,10 @@ void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern } } } + if (ctx.repo->enable_commit_graph) { + static const char *graph_arg = "--graph"; + vector_push(&vec, &graph_arg, 0); + } if (path) { arg = "--"; @@ -242,8 +301,10 @@ void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern if (pager) html(""); - html("" - ""); + if (ctx.repo->enable_commit_graph) + html(""); + html("
AgeCommit message"); + html("
AgeCommit message"); if (pager) { html(" ("); cgit_log_link(ctx.qry.showmsg ? "Collapse" : "Expand", NULL, @@ -274,7 +335,7 @@ void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern } for (i = 0; i < cnt && (commit = get_revision(&rev)) != NULL; i++) { - print_commit(commit); + print_commit(commit, &rev); free(commit->buffer); commit->buffer = NULL; free_commit_list(commit->parents); -- cgit v1.2.3-70-g09d2