all repos — cgit @ 6cb326c83b3c0b35d472305294afee3105b3088d

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