all repos — cgit @ 9d8d9b61238df3a855504825e5f735d00289f12b

a hyperfast web frontend for git written in c

ui-commit.c (view raw)

  1/* ui-commit.c: generate commit view
  2 *
  3 * Copyright (C) 2006 Lars Hjemli
  4 *
  5 * Licensed under GNU General Public License v2
  6 *   (see COPYING for full license text)
  7 */
  8
  9#include "cgit.h"
 10
 11int files = 0;
 12
 13void print_filepair(struct diff_filepair *pair)
 14{
 15	char *query;
 16	char *class;
 17	
 18	switch (pair->status) {
 19	case DIFF_STATUS_ADDED:
 20		class = "add";
 21		break;
 22	case DIFF_STATUS_COPIED:
 23		class = "cpy";
 24		break;
 25	case DIFF_STATUS_DELETED:
 26		class = "del";
 27		break;
 28	case DIFF_STATUS_MODIFIED:
 29		class = "upd";
 30		break;
 31	case DIFF_STATUS_RENAMED:
 32		class = "mov";
 33		break;
 34	case DIFF_STATUS_TYPE_CHANGED:
 35		class = "typ";
 36		break;
 37	case DIFF_STATUS_UNKNOWN:
 38		class = "unk";
 39		break;
 40	case DIFF_STATUS_UNMERGED:
 41		class = "stg";
 42		break;
 43	default:
 44		die("bug: unhandled diff status %c", pair->status);
 45	}
 46
 47	html("<tr>");
 48	htmlf("<td class='mode'>");
 49	if (is_null_sha1(pair->two->sha1)) {
 50		html_filemode(pair->one->mode);
 51	} else {
 52		html_filemode(pair->two->mode);
 53	}
 54
 55	if (pair->one->mode != pair->two->mode && 
 56	    !is_null_sha1(pair->one->sha1) && 
 57	    !is_null_sha1(pair->two->sha1)) {
 58		html("<span class='modechange'>[");
 59		html_filemode(pair->one->mode);
 60		html("]</span>");
 61	}
 62	htmlf("</td><td class='%s'>", class);
 63	query = fmt("id=%s", sha1_to_hex(pair->two->sha1));	
 64	html_link_open(cgit_pageurl(cgit_query_repo, "view", query), 
 65		       NULL, NULL);
 66	if (pair->status == DIFF_STATUS_COPIED || 
 67	    pair->status == DIFF_STATUS_RENAMED) {
 68		html_txt(pair->two->path);
 69		htmlf("</a> (%s from ", pair->status == DIFF_STATUS_COPIED ? 
 70		      "copied" : "renamed");
 71		query = fmt("id=%s", sha1_to_hex(pair->one->sha1));	
 72		html_link_open(cgit_pageurl(cgit_query_repo, "view", query), 
 73			       NULL, NULL);
 74		html_txt(pair->one->path);
 75		html("</a>)");
 76	} else {
 77		html_txt(pair->two->path);
 78		html("</a>");
 79	}
 80	html("<td>");
 81
 82	//TODO: diffstat graph
 83	
 84	html("</td></tr>\n");
 85	files++;	
 86}
 87
 88void diff_format_cb(struct diff_queue_struct *q,
 89		    struct diff_options *options, void *data)
 90{
 91	int i;
 92
 93	for (i = 0; i < q->nr; i++) {
 94		if (q->queue[i]->status == 'U')
 95			continue;
 96		print_filepair(q->queue[i]);
 97	}
 98}
 99
100void cgit_diffstat(struct commit *commit)
101{
102	struct diff_options opt;
103	int ret;
104
105	diff_setup(&opt);
106	opt.output_format = DIFF_FORMAT_CALLBACK;
107	opt.detect_rename = 1;
108	opt.recursive = 1;
109	opt.format_callback = diff_format_cb;
110	diff_setup_done(&opt);
111	
112	if (commit->parents)
113		ret = diff_tree_sha1(commit->parents->item->object.sha1,
114				     commit->object.sha1,
115				     "", &opt);
116	else
117		ret = diff_root_tree_sha1(commit->object.sha1, "", &opt);
118
119	diffcore_std(&opt);
120	diff_flush(&opt);
121}
122
123void cgit_print_commit(const char *hex)
124{
125	struct commit *commit;
126	struct commitinfo *info;
127	struct commit_list *p;
128	unsigned char sha1[20];
129	char *query;
130
131	if (get_sha1(hex, sha1)) {
132		cgit_print_error(fmt("Bad object id: %s", hex));
133		return;
134	}
135	commit = lookup_commit_reference(sha1);
136	if (!commit) {
137		cgit_print_error(fmt("Bad commit reference: %s", hex));
138		return;
139	}
140	info = cgit_parse_commit(commit);
141
142	html("<table class='commit-info'>\n");
143	html("<tr><th>author</th><td>");
144	html_txt(info->author);
145	html(" ");
146	html_txt(info->author_email);
147	html("</td><td class='right'>");
148	cgit_print_date(info->author_date);
149	html("</td></tr>\n");
150	html("<tr><th>committer</th><td>");
151	html_txt(info->committer);
152	html(" ");
153	html_txt(info->committer_email);
154	html("</td><td class='right'>");
155	cgit_print_date(info->committer_date);
156	html("</td></tr>\n");
157	html("<tr><th>tree</th><td colspan='2' class='sha1'><a href='");
158	query = fmt("id=%s", sha1_to_hex(commit->tree->object.sha1));
159	html_attr(cgit_pageurl(cgit_query_repo, "tree", query));
160	htmlf("'>%s</a></td></tr>\n", sha1_to_hex(commit->tree->object.sha1));
161      	for (p = commit->parents; p ; p = p->next) {
162		html("<tr><th>parent</th>"
163		     "<td colspan='2' class='sha1'>"
164		     "<a href='");
165		query = fmt("id=%s", sha1_to_hex(p->item->object.sha1));
166		html_attr(cgit_pageurl(cgit_query_repo, "commit", query));
167		htmlf("'>%s</a></td></tr>\n", 
168		      sha1_to_hex(p->item->object.sha1));
169	}
170	html("</table>\n");
171	html("<div class='commit-subject'>");
172	html_txt(info->subject);
173	html("</div>");
174	html("<div class='commit-msg'>");
175	html_txt(info->msg);
176	html("</div>");
177	html("<table class='diffstat'>");
178	html("<tr><th colspan='3'>Affected files</tr>\n");
179	cgit_diffstat(commit);
180	htmlf("<tr><td colspan='3' class='summary'>"
181	      "%d file%s changed</td></tr>\n", files, files > 1 ? "s" : "");
182	html("</table>");
183	cgit_free_commitinfo(info);
184}