all repos — cgit @ ac1f493b6bbc589327e9ba3303f112fcd323c6b6

a hyperfast web frontend for git written in c

ui-summary.c (view raw)

  1/* ui-summary.c: functions for generating repo summary page
  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
 11static int header;
 12
 13static int cmp_age(int age1, int age2)
 14{
 15	if (age1 != 0 && age2 != 0)
 16		return age2 - age1;
 17
 18	if (age1 == 0 && age2 == 0)
 19		return 0;
 20
 21	if (age1 == 0)
 22		return +1;
 23
 24	return -1;
 25}
 26
 27static int cmp_ref_name(const void *a, const void *b)
 28{
 29	struct refinfo *r1 = *(struct refinfo **)a;
 30	struct refinfo *r2 = *(struct refinfo **)b;
 31
 32	return strcmp(r1->refname, r2->refname);
 33}
 34
 35static int cmp_branch_age(const void *a, const void *b)
 36{
 37	struct refinfo *r1 = *(struct refinfo **)a;
 38	struct refinfo *r2 = *(struct refinfo **)b;
 39
 40	return cmp_age(r1->commit->committer_date, r2->commit->committer_date);
 41}
 42
 43static int cmp_tag_age(const void *a, const void *b)
 44{
 45	struct refinfo *r1 = *(struct refinfo **)a;
 46	struct refinfo *r2 = *(struct refinfo **)b;
 47
 48	return cmp_age(r1->tag->tagger_date, r2->tag->tagger_date);
 49}
 50
 51static void cgit_print_branch(struct refinfo *ref)
 52{
 53	struct commit *commit;
 54	struct commitinfo *info;
 55	char *name = (char *)ref->refname;
 56
 57	commit = lookup_commit(ref->object->sha1);
 58	// object is not really parsed at this point, because of some fallout
 59	// from previous calls to git functions in cgit_print_log()
 60	commit->object.parsed = 0;
 61	if (commit && !parse_commit(commit)){
 62		info = cgit_parse_commit(commit);
 63		html("<tr><td>");
 64		cgit_log_link(name, NULL, NULL, name, NULL, NULL, 0);
 65		html("</td><td>");
 66		cgit_print_age(commit->date, -1, NULL);
 67		html("</td><td>");
 68		html_txt(info->author);
 69		html("</td><td>");
 70		cgit_commit_link(info->subject, NULL, NULL, name, NULL);
 71		html("</td></tr>\n");
 72		cgit_free_commitinfo(info);
 73	} else {
 74		html("<tr><td>");
 75		html_txt(name);
 76		html("</td><td colspan='3'>");
 77		htmlf("*** bad ref %s ***", sha1_to_hex(ref->object->sha1));
 78		html("</td></tr>\n");
 79	}
 80}
 81
 82static void print_tag_header()
 83{
 84	html("<tr class='nohover'><th class='left'>Tag</th>"
 85	     "<th class='left'>Age</th>"
 86	     "<th class='left'>Author</th>"
 87	     "<th class='left'>Reference</th></tr>\n");
 88	header = 1;
 89}
 90
 91static int print_tag(struct refinfo *ref)
 92{
 93	struct tag *tag;
 94	struct taginfo *info;
 95	char *url, *name = (char *)ref->refname;
 96
 97	if (ref->object->type == OBJ_TAG) {
 98		tag = lookup_tag(ref->object->sha1);
 99		if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag)))
100			return 2;
101		html("<tr><td>");
102		url = cgit_pageurl(cgit_query_repo, "tag",
103				   fmt("id=%s", name));
104		html_link_open(url, NULL, NULL);
105		html_txt(name);
106		html_link_close();
107		html("</td><td>");
108		if (info->tagger_date > 0)
109			cgit_print_age(info->tagger_date, -1, NULL);
110		html("</td><td>");
111		if (info->tagger)
112			html(info->tagger);
113		html("</td><td>");
114		cgit_object_link(tag->tagged);
115		html("</td></tr>\n");
116	} else {
117		if (!header)
118			print_tag_header();
119		html("<tr><td>");
120		html_txt(name);
121		html("</td><td colspan='2'/><td>");
122		cgit_object_link(ref->object);
123		html("</td></tr>\n");
124	}
125	return 0;
126}
127
128static int cgit_print_archive_cb(const char *refname, const unsigned char *sha1,
129				 int flags, void *cb_data)
130{
131	struct tag *tag;
132	struct taginfo *info;
133	struct object *obj;
134	char buf[256], *url;
135	unsigned char fileid[20];
136
137	if (prefixcmp(refname, "refs/archives"))
138		return 0;
139	strncpy(buf, refname+14, sizeof(buf));
140	obj = parse_object(sha1);
141	if (!obj)
142		return 1;
143	if (obj->type == OBJ_TAG) {
144		tag = lookup_tag(sha1);
145		if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag)))
146			return 0;
147		hashcpy(fileid, tag->tagged->sha1);
148	} else if (obj->type != OBJ_BLOB) {
149		return 0;
150	} else {
151		hashcpy(fileid, sha1);
152	}
153	if (!header) {
154		html("<table id='downloads'>");
155		html("<tr><th>Downloads</th></tr>");
156		header = 1;
157	}
158	html("<tr><td>");
159	url = cgit_pageurl(cgit_query_repo, "blob",
160			   fmt("id=%s&amp;path=%s", sha1_to_hex(fileid),
161			       buf));
162	html_link_open(url, NULL, NULL);
163	html_txt(buf);
164	html_link_close();
165	html("</td></tr>");
166	return 0;
167}
168
169static void print_refs_link(char *path)
170{
171	html("<tr class='nohover'><td colspan='4'>");
172	cgit_refs_link("[...]", NULL, NULL, cgit_query_head, NULL, path);
173	html("</td></tr>");
174}
175
176void cgit_print_branches(int maxcount)
177{
178	struct reflist list;
179	int i;
180
181	html("<tr class='nohover'><th class='left'>Branch</th>"
182	     "<th class='left'>Idle</th>"
183	     "<th class='left'>Author</th>"
184	     "<th class='left'>Head commit</th></tr>\n");
185
186	list.refs = NULL;
187	list.alloc = list.count = 0;
188	for_each_branch_ref(cgit_refs_cb, &list);
189
190	if (maxcount == 0 || maxcount > list.count)
191		maxcount = list.count;
192
193	if (maxcount < list.count) {
194		qsort(list.refs, list.count, sizeof(*list.refs), cmp_branch_age);
195		qsort(list.refs, maxcount, sizeof(*list.refs), cmp_ref_name);
196	}
197
198	for(i=0; i<maxcount; i++)
199		cgit_print_branch(list.refs[i]);
200
201	if (maxcount < list.count)
202		print_refs_link("heads");
203}
204
205void cgit_print_tags(int maxcount)
206{
207	struct reflist list;
208	int i;
209
210	header = 0;
211	list.refs = NULL;
212	list.alloc = list.count = 0;
213	for_each_tag_ref(cgit_refs_cb, &list);
214	if (list.count == 0)
215		return;
216	qsort(list.refs, list.count, sizeof(*list.refs), cmp_tag_age);
217	if (!maxcount)
218		maxcount = list.count;
219	else if (maxcount > list.count)
220		maxcount = list.count;
221	print_tag_header();
222	for(i=0; i<maxcount; i++)
223		print_tag(list.refs[i]);
224
225	if (maxcount < list.count)
226		print_refs_link("tags");
227}
228
229static void cgit_print_archives()
230{
231	header = 0;
232	for_each_ref(cgit_print_archive_cb, NULL);
233	if (header)
234		html("</table>");
235}
236
237void cgit_print_summary()
238{
239	html("<div id='summary'>");
240	cgit_print_archives();
241	html("<h2>");
242	html_txt(cgit_repo->name);
243	html(" - ");
244	html_txt(cgit_repo->desc);
245	html("</h2>");
246	if (cgit_repo->readme)
247		html_include(cgit_repo->readme);
248	html("</div>");
249	if (cgit_summary_log > 0)
250		cgit_print_log(cgit_query_head, 0, cgit_summary_log, NULL, NULL, 0);
251	html("<table class='list nowrap'>");
252	if (cgit_summary_log > 0)
253		html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>");
254	cgit_print_branches(cgit_summary_branches);
255	html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>");
256	cgit_print_tags(cgit_summary_tags);
257	html("</table>");
258}