all repos — cgit @ 06c81d6faafff1c80bc9e2302e5b8fea393b775b

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&id2=%s", sha1_to_hex(pair->one->sha1), 
 64		    sha1_to_hex(pair->two->sha1));	
 65	html_link_open(cgit_pageurl(cgit_query_repo, "diff", query), 
 66		       NULL, NULL);
 67	if (pair->status == DIFF_STATUS_COPIED || 
 68	    pair->status == DIFF_STATUS_RENAMED) {
 69		html_txt(pair->two->path);
 70		htmlf("</a> (%s from ", pair->status == DIFF_STATUS_COPIED ? 
 71		      "copied" : "renamed");
 72		query = fmt("id=%s", sha1_to_hex(pair->one->sha1));	
 73		html_link_open(cgit_pageurl(cgit_query_repo, "view", query), 
 74			       NULL, NULL);
 75		html_txt(pair->one->path);
 76		html("</a>)");
 77	} else {
 78		html_txt(pair->two->path);
 79		html("</a>");
 80	}
 81	html("<td>");
 82
 83	//TODO: diffstat graph
 84	
 85	html("</td></tr>\n");
 86	files++;	
 87}
 88
 89void diff_format_cb(struct diff_queue_struct *q,
 90		    struct diff_options *options, void *data)
 91{
 92	int i;
 93
 94	for (i = 0; i < q->nr; i++) {
 95		if (q->queue[i]->status == 'U')
 96			continue;
 97		print_filepair(q->queue[i]);
 98	}
 99}
100
101void cgit_diffstat(struct commit *commit)
102{
103	struct diff_options opt;
104	int ret;
105
106	diff_setup(&opt);
107	opt.output_format = DIFF_FORMAT_CALLBACK;
108	opt.detect_rename = 1;
109	opt.recursive = 1;
110	opt.format_callback = diff_format_cb;
111	diff_setup_done(&opt);
112	
113	if (commit->parents)
114		ret = diff_tree_sha1(commit->parents->item->object.sha1,
115				     commit->object.sha1,
116				     "", &opt);
117	else
118		ret = diff_root_tree_sha1(commit->object.sha1, "", &opt);
119
120	diffcore_std(&opt);
121	diff_flush(&opt);
122}
123
124void cgit_print_commit(const char *hex)
125{
126	struct commit *commit;
127	struct commitinfo *info;
128	struct commit_list *p;
129	unsigned char sha1[20];
130	char *query;
131
132	if (get_sha1(hex, sha1)) {
133		cgit_print_error(fmt("Bad object id: %s", hex));
134		return;
135	}
136	commit = lookup_commit_reference(sha1);
137	if (!commit) {
138		cgit_print_error(fmt("Bad commit reference: %s", hex));
139		return;
140	}
141	info = cgit_parse_commit(commit);
142
143	html("<table class='commit-info'>\n");
144	html("<tr><th>author</th><td>");
145	html_txt(info->author);
146	html(" ");
147	html_txt(info->author_email);
148	html("</td><td class='right'>");
149	cgit_print_date(info->author_date);
150	html("</td></tr>\n");
151	html("<tr><th>committer</th><td>");
152	html_txt(info->committer);
153	html(" ");
154	html_txt(info->committer_email);
155	html("</td><td class='right'>");
156	cgit_print_date(info->committer_date);
157	html("</td></tr>\n");
158	html("<tr><th>tree</th><td colspan='2' class='sha1'><a href='");
159	query = fmt("id=%s", sha1_to_hex(commit->tree->object.sha1));
160	html_attr(cgit_pageurl(cgit_query_repo, "tree", query));
161	htmlf("'>%s</a></td></tr>\n", sha1_to_hex(commit->tree->object.sha1));
162      	for (p = commit->parents; p ; p = p->next) {
163		html("<tr><th>parent</th>"
164		     "<td colspan='2' class='sha1'>"
165		     "<a href='");
166		query = fmt("id=%s", sha1_to_hex(p->item->object.sha1));
167		html_attr(cgit_pageurl(cgit_query_repo, "commit", query));
168		htmlf("'>%s</a></td></tr>\n", 
169		      sha1_to_hex(p->item->object.sha1));
170	}
171	html("</table>\n");
172	html("<div class='commit-subject'>");
173	html_txt(info->subject);
174	html("</div>");
175	html("<div class='commit-msg'>");
176	html_txt(info->msg);
177	html("</div>");
178	html("<table class='diffstat'>");
179	html("<tr><th colspan='3'>Affected files</tr>\n");
180	cgit_diffstat(commit);
181	htmlf("<tr><td colspan='3' class='summary'>"
182	      "%d file%s changed</td></tr>\n", files, files > 1 ? "s" : "");
183	html("</table>");
184	cgit_free_commitinfo(info);
185}