about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--cgit.c5
-rw-r--r--cgit.css11
-rw-r--r--cgit.h31
-rw-r--r--cgitrc17
-rwxr-xr-xgen-version.sh2
-rw-r--r--shared.c64
-rw-r--r--ui-commit.c4
-rw-r--r--ui-diff.c45
-rw-r--r--ui-refs.c30
-rw-r--r--ui-shared.c6
-rw-r--r--ui-summary.c172
12 files changed, 299 insertions, 90 deletions
diff --git a/Makefile b/Makefile index 8e3da72..36b5ff6 100644 --- a/Makefile +++ b/Makefile
@@ -16,7 +16,7 @@ GIT_URL = http://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.bz2
16EXTLIBS = git/libgit.a git/xdiff/lib.a -lz -lcrypto 16EXTLIBS = git/libgit.a git/xdiff/lib.a -lz -lcrypto
17OBJECTS = shared.o cache.o parsing.o html.o ui-shared.o ui-repolist.o \ 17OBJECTS = shared.o cache.o parsing.o html.o ui-shared.o ui-repolist.o \
18 ui-summary.o ui-log.o ui-tree.o ui-commit.o ui-diff.o \ 18 ui-summary.o ui-log.o ui-tree.o ui-commit.o ui-diff.o \
19 ui-snapshot.o ui-blob.o ui-tag.o 19 ui-snapshot.o ui-blob.o ui-tag.o ui-refs.o
20 20
21 21
22.PHONY: all git install clean distclean force-version get-git 22.PHONY: all git install clean distclean force-version get-git
diff --git a/cgit.c b/cgit.c index c86d290..cc18ed4 100644 --- a/cgit.c +++ b/cgit.c
@@ -103,11 +103,14 @@ static void cgit_print_repo_page(struct cacheitem *item)
103 case CMD_COMMIT: 103 case CMD_COMMIT:
104 cgit_print_commit(cgit_query_sha1); 104 cgit_print_commit(cgit_query_sha1);
105 break; 105 break;
106 case CMD_REFS:
107 cgit_print_refs();
108 break;
106 case CMD_TAG: 109 case CMD_TAG:
107 cgit_print_tag(cgit_query_sha1); 110 cgit_print_tag(cgit_query_sha1);
108 break; 111 break;
109 case CMD_DIFF: 112 case CMD_DIFF:
110 cgit_print_diff(cgit_query_sha1, cgit_query_sha2); 113 cgit_print_diff(cgit_query_sha1, cgit_query_sha2, cgit_query_path);
111 break; 114 break;
112 default: 115 default:
113 cgit_print_error("Invalid request"); 116 cgit_print_error("Invalid request");
diff --git a/cgit.css b/cgit.css index 65ff5c3..b8c3d81 100644 --- a/cgit.css +++ b/cgit.css
@@ -272,10 +272,6 @@ table.diffstat {
272 background-color: #eee; 272 background-color: #eee;
273} 273}
274 274
275table.diffstat tr:hover {
276 background-color: #ccc;
277}
278
279table.diffstat th { 275table.diffstat th {
280 font-weight: normal; 276 font-weight: normal;
281 text-align: left; 277 text-align: left;
@@ -339,6 +335,10 @@ div.diffstat-summary {
339 padding-top: 0.5em; 335 padding-top: 0.5em;
340} 336}
341 337
338table.diff {
339 width: 100%;
340}
341
342table.diff td { 342table.diff td {
343 font-family: monospace; 343 font-family: monospace;
344 white-space: pre; 344 white-space: pre;
@@ -346,7 +346,8 @@ table.diff td {
346 346
347table.diff td div.head { 347table.diff td div.head {
348 font-weight: bold; 348 font-weight: bold;
349 padding-top: 1em; 349 margin-top: 1em;
350 background-color: #eee;
350} 351}
351 352
352table.diff td div.hunk { 353table.diff td div.hunk {
diff --git a/cgit.h b/cgit.h index e3d9cb8..f8f0316 100644 --- a/cgit.h +++ b/cgit.h
@@ -28,6 +28,7 @@
28#define CMD_BLOB 5 28#define CMD_BLOB 5
29#define CMD_SNAPSHOT 6 29#define CMD_SNAPSHOT 6
30#define CMD_TAG 7 30#define CMD_TAG 7
31#define CMD_REFS 8
31 32
32/* 33/*
33 * Dateformats used on misc. pages 34 * Dateformats used on misc. pages
@@ -98,6 +99,21 @@ struct taginfo {
98 char *msg; 99 char *msg;
99}; 100};
100 101
102struct refinfo {
103 const char *refname;
104 struct object *object;
105 union {
106 struct taginfo *tag;
107 struct commitinfo *commit;
108 };
109};
110
111struct reflist {
112 struct refinfo **refs;
113 int alloc;
114 int count;
115};
116
101extern const char *cgit_version; 117extern const char *cgit_version;
102 118
103extern struct repolist cgit_repolist; 119extern struct repolist cgit_repolist;
@@ -128,6 +144,8 @@ extern int cgit_cache_dynamic_ttl;
128extern int cgit_cache_static_ttl; 144extern int cgit_cache_static_ttl;
129extern int cgit_cache_max_create_time; 145extern int cgit_cache_max_create_time;
130extern int cgit_summary_log; 146extern int cgit_summary_log;
147extern int cgit_summary_tags;
148extern int cgit_summary_branches;
131 149
132extern int cgit_max_msg_len; 150extern int cgit_max_msg_len;
133extern int cgit_max_repodesc_len; 151extern int cgit_max_repodesc_len;
@@ -162,6 +180,10 @@ extern int chk_non_negative(int result, char *msg);
162extern int hextoint(char c); 180extern int hextoint(char c);
163extern char *trim_end(const char *str, char c); 181extern char *trim_end(const char *str, char c);
164 182
183extern void cgit_add_ref(struct reflist *list, struct refinfo *ref);
184extern int cgit_refs_cb(const char *refname, const unsigned char *sha1,
185 int flags, void *cb_data);
186
165extern void *cgit_free_commitinfo(struct commitinfo *info); 187extern void *cgit_free_commitinfo(struct commitinfo *info);
166 188
167extern int cgit_diff_files(const unsigned char *old_sha1, 189extern int cgit_diff_files(const unsigned char *old_sha1,
@@ -170,7 +192,7 @@ extern int cgit_diff_files(const unsigned char *old_sha1,
170 192
171extern void cgit_diff_tree(const unsigned char *old_sha1, 193extern void cgit_diff_tree(const unsigned char *old_sha1,
172 const unsigned char *new_sha1, 194 const unsigned char *new_sha1,
173 filepair_fn fn); 195 filepair_fn fn, const char *prefix);
174 196
175extern void cgit_diff_commit(struct commit *commit, filepair_fn fn); 197extern void cgit_diff_commit(struct commit *commit, filepair_fn fn);
176 198
@@ -214,6 +236,8 @@ extern void cgit_log_link(char *name, char *title, char *class, char *head,
214 char *rev, char *path, int ofs); 236 char *rev, char *path, int ofs);
215extern void cgit_commit_link(char *name, char *title, char *class, char *head, 237extern void cgit_commit_link(char *name, char *title, char *class, char *head,
216 char *rev); 238 char *rev);
239extern void cgit_refs_link(char *name, char *title, char *class, char *head,
240 char *rev, char *path);
217extern void cgit_snapshot_link(char *name, char *title, char *class, 241extern void cgit_snapshot_link(char *name, char *title, char *class,
218 char *head, char *rev, char *archivename); 242 char *head, char *rev, char *archivename);
219extern void cgit_diff_link(char *name, char *title, char *class, char *head, 243extern void cgit_diff_link(char *name, char *title, char *class, char *head,
@@ -230,6 +254,8 @@ extern void cgit_print_pageheader(char *title, int show_search);
230extern void cgit_print_snapshot_start(const char *mimetype, 254extern void cgit_print_snapshot_start(const char *mimetype,
231 const char *filename, 255 const char *filename,
232 struct cacheitem *item); 256 struct cacheitem *item);
257extern void cgit_print_branches(int maxcount);
258extern void cgit_print_tags(int maxcount);
233 259
234extern void cgit_print_repolist(struct cacheitem *item); 260extern void cgit_print_repolist(struct cacheitem *item);
235extern void cgit_print_summary(); 261extern void cgit_print_summary();
@@ -237,8 +263,9 @@ extern void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *
237extern void cgit_print_blob(struct cacheitem *item, const char *hex, char *path); 263extern void cgit_print_blob(struct cacheitem *item, const char *hex, char *path);
238extern void cgit_print_tree(const char *rev, char *path); 264extern void cgit_print_tree(const char *rev, char *path);
239extern void cgit_print_commit(char *hex); 265extern void cgit_print_commit(char *hex);
266extern void cgit_print_refs();
240extern void cgit_print_tag(char *revname); 267extern void cgit_print_tag(char *revname);
241extern void cgit_print_diff(const char *new_hex, const char *old_hex); 268extern void cgit_print_diff(const char *new_hex, const char *old_hex, const char *prefix);
242extern void cgit_print_snapshot(struct cacheitem *item, const char *head, 269extern void cgit_print_snapshot(struct cacheitem *item, const char *head,
243 const char *hex, const char *prefix, 270 const char *hex, const char *prefix,
244 const char *filename, int snapshot); 271 const char *filename, int snapshot);
diff --git a/cgitrc b/cgitrc index 34ea116..2b09e01 100644 --- a/cgitrc +++ b/cgitrc
@@ -30,6 +30,16 @@
30#summary-log=0 30#summary-log=0
31 31
32 32
33## Restrict the number of branches printed in summary view. Set to 0 to
34## print all branches.
35#summary-branches=0
36
37
38## Restrict the number of tags printed in summary view. Set to 0 to
39## print all tags.
40#summary-tags=0
41
42
33## The "Idle" column on the repository index page can read a timestamp 43## The "Idle" column on the repository index page can read a timestamp
34## from the specified agefile (if this file cannot be found, the mtime 44## from the specified agefile (if this file cannot be found, the mtime
35## of HEAD is used). 45## of HEAD is used).
@@ -41,6 +51,13 @@
41#agefile=info/web/last-modified 51#agefile=info/web/last-modified
42 52
43 53
54## Git detects renames, but with a limit on the number of files to
55## consider. This option can be used to specify another limit (or -1 to
56## use the default limit).
57##
58#renamelimit=-1
59
60
44## Specify a root for virtual urls. This makes cgit generate urls like 61## Specify a root for virtual urls. This makes cgit generate urls like
45## 62##
46## http://localhost/git/repo/log/?h=branch 63## http://localhost/git/repo/log/?h=branch
diff --git a/gen-version.sh b/gen-version.sh index 739c83e..3a08015 100755 --- a/gen-version.sh +++ b/gen-version.sh
@@ -6,7 +6,7 @@ V=$1
6# Use `git describe` to get current version if we're inside a git repo 6# Use `git describe` to get current version if we're inside a git repo
7if test -d .git 7if test -d .git
8then 8then
9 V=$(git describe --abbrev=4 HEAD 2>/dev/null | sed -e 's/-/./g') 9 V=$(git describe --abbrev=4 HEAD 2>/dev/null)
10fi 10fi
11 11
12new="CGIT_VERSION = $V" 12new="CGIT_VERSION = $V"
diff --git a/shared.c b/shared.c index 0fe513f..7eb2b0e 100644 --- a/shared.c +++ b/shared.c
@@ -38,6 +38,9 @@ int cgit_cache_dynamic_ttl = 5;
38int cgit_cache_static_ttl = -1; 38int cgit_cache_static_ttl = -1;
39int cgit_cache_max_create_time = 5; 39int cgit_cache_max_create_time = 5;
40int cgit_summary_log = 0; 40int cgit_summary_log = 0;
41int cgit_summary_tags = 0;
42int cgit_summary_branches = 0;
43int cgit_renamelimit = -1;
41 44
42int cgit_max_msg_len = 60; 45int cgit_max_msg_len = 60;
43int cgit_max_repodesc_len = 60; 46int cgit_max_repodesc_len = 60;
@@ -63,7 +66,7 @@ int htmlfd = 0;
63int cgit_get_cmd_index(const char *cmd) 66int cgit_get_cmd_index(const char *cmd)
64{ 67{
65 static char *cmds[] = {"log", "commit", "diff", "tree", "blob", 68 static char *cmds[] = {"log", "commit", "diff", "tree", "blob",
66 "snapshot", "tag", NULL}; 69 "snapshot", "tag", "refs", NULL};
67 int i; 70 int i;
68 71
69 for(i = 0; cmds[i]; i++) 72 for(i = 0; cmds[i]; i++)
@@ -180,8 +183,14 @@ void cgit_global_config_cb(const char *name, const char *value)
180 cgit_max_commit_count = atoi(value); 183 cgit_max_commit_count = atoi(value);
181 else if (!strcmp(name, "summary-log")) 184 else if (!strcmp(name, "summary-log"))
182 cgit_summary_log = atoi(value); 185 cgit_summary_log = atoi(value);
186 else if (!strcmp(name, "summary-branches"))
187 cgit_summary_branches = atoi(value);
188 else if (!strcmp(name, "summary-tags"))
189 cgit_summary_tags = atoi(value);
183 else if (!strcmp(name, "agefile")) 190 else if (!strcmp(name, "agefile"))
184 cgit_agefile = xstrdup(value); 191 cgit_agefile = xstrdup(value);
192 else if (!strcmp(name, "renamelimit"))
193 cgit_renamelimit = atoi(value);
185 else if (!strcmp(name, "repo.group")) 194 else if (!strcmp(name, "repo.group"))
186 cgit_repo_group = xstrdup(value); 195 cgit_repo_group = xstrdup(value);
187 else if (!strcmp(name, "repo.url")) 196 else if (!strcmp(name, "repo.url"))
@@ -288,6 +297,47 @@ char *trim_end(const char *str, char c)
288 return s; 297 return s;
289} 298}
290 299
300void cgit_add_ref(struct reflist *list, struct refinfo *ref)
301{
302 size_t size;
303
304 if (list->count >= list->alloc) {
305 list->alloc += (list->alloc ? list->alloc : 4);
306 size = list->alloc * sizeof(struct refinfo *);
307 list->refs = xrealloc(list->refs, size);
308 }
309 list->refs[list->count++] = ref;
310}
311
312struct refinfo *cgit_mk_refinfo(const char *refname, const unsigned char *sha1)
313{
314 struct refinfo *ref;
315
316 ref = xmalloc(sizeof (struct refinfo));
317 ref->refname = xstrdup(refname);
318 ref->object = parse_object(sha1);
319 switch (ref->object->type) {
320 case OBJ_TAG:
321 ref->tag = cgit_parse_tag((struct tag *)ref->object);
322 break;
323 case OBJ_COMMIT:
324 ref->commit = cgit_parse_commit((struct commit *)ref->object);
325 break;
326 }
327 return ref;
328}
329
330int cgit_refs_cb(const char *refname, const unsigned char *sha1, int flags,
331 void *cb_data)
332{
333 struct reflist *list = (struct reflist *)cb_data;
334 struct refinfo *info = cgit_mk_refinfo(refname, sha1);
335
336 if (info)
337 cgit_add_ref(list, info);
338 return 0;
339}
340
291void cgit_diff_tree_cb(struct diff_queue_struct *q, 341void cgit_diff_tree_cb(struct diff_queue_struct *q,
292 struct diff_options *options, void *data) 342 struct diff_options *options, void *data)
293{ 343{
@@ -383,17 +433,25 @@ int cgit_diff_files(const unsigned char *old_sha1,
383 433
384void cgit_diff_tree(const unsigned char *old_sha1, 434void cgit_diff_tree(const unsigned char *old_sha1,
385 const unsigned char *new_sha1, 435 const unsigned char *new_sha1,
386 filepair_fn fn) 436 filepair_fn fn, const char *prefix)
387{ 437{
388 struct diff_options opt; 438 struct diff_options opt;
389 int ret; 439 int ret;
440 int prefixlen;
390 441
391 diff_setup(&opt); 442 diff_setup(&opt);
392 opt.output_format = DIFF_FORMAT_CALLBACK; 443 opt.output_format = DIFF_FORMAT_CALLBACK;
393 opt.detect_rename = 1; 444 opt.detect_rename = 1;
445 opt.rename_limit = cgit_renamelimit;
394 opt.recursive = 1; 446 opt.recursive = 1;
395 opt.format_callback = cgit_diff_tree_cb; 447 opt.format_callback = cgit_diff_tree_cb;
396 opt.format_callback_data = fn; 448 opt.format_callback_data = fn;
449 if (prefix) {
450 opt.nr_paths = 1;
451 opt.paths = &prefix;
452 prefixlen = strlen(prefix);
453 opt.pathlens = &prefixlen;
454 }
397 diff_setup_done(&opt); 455 diff_setup_done(&opt);
398 456
399 if (old_sha1 && !is_null_sha1(old_sha1)) 457 if (old_sha1 && !is_null_sha1(old_sha1))
@@ -410,5 +468,5 @@ void cgit_diff_commit(struct commit *commit, filepair_fn fn)
410 468
411 if (commit->parents) 469 if (commit->parents)
412 old_sha1 = commit->parents->item->object.sha1; 470 old_sha1 = commit->parents->item->object.sha1;
413 cgit_diff_tree(old_sha1, commit->object.sha1, fn); 471 cgit_diff_tree(old_sha1, commit->object.sha1, fn, NULL);
414} 472}
diff --git a/ui-commit.c b/ui-commit.c index 90e09ed..4ac8955 100644 --- a/ui-commit.c +++ b/ui-commit.c
@@ -75,8 +75,8 @@ void print_fileinfo(struct fileinfo *info)
75 html("]</span>"); 75 html("]</span>");
76 } 76 }
77 htmlf("</td><td class='%s'>", class); 77 htmlf("</td><td class='%s'>", class);
78 cgit_tree_link(info->new_path, NULL, NULL, cgit_query_head, curr_rev, 78 cgit_diff_link(info->new_path, NULL, NULL, cgit_query_head, curr_rev,
79 info->new_path); 79 NULL, info->new_path);
80 if (info->status == DIFF_STATUS_COPIED || info->status == DIFF_STATUS_RENAMED) 80 if (info->status == DIFF_STATUS_COPIED || info->status == DIFF_STATUS_RENAMED)
81 htmlf(" (%s from %s)", 81 htmlf(" (%s from %s)",
82 info->status == DIFF_STATUS_COPIED ? "copied" : "renamed", 82 info->status == DIFF_STATUS_COPIED ? "copied" : "renamed",
diff --git a/ui-diff.c b/ui-diff.c index 0be845f..ac9a3fa 100644 --- a/ui-diff.c +++ b/ui-diff.c
@@ -9,6 +9,9 @@
9#include "cgit.h" 9#include "cgit.h"
10 10
11 11
12unsigned char old_rev_sha1[20];
13unsigned char new_rev_sha1[20];
14
12/* 15/*
13 * print a single line returned from xdiff 16 * print a single line returned from xdiff
14 */ 17 */
@@ -67,9 +70,17 @@ static void header(unsigned char *sha1, char *path1, int mode1,
67 htmlf("..%.6o", mode2); 70 htmlf("..%.6o", mode2);
68 } 71 }
69 html("<br/>--- a/"); 72 html("<br/>--- a/");
70 html_txt(path1); 73 if (mode1 != 0)
74 cgit_tree_link(path1, NULL, NULL, cgit_query_head,
75 sha1_to_hex(old_rev_sha1), path1);
76 else
77 html_txt(path1);
71 html("<br/>+++ b/"); 78 html("<br/>+++ b/");
72 html_txt(path2); 79 if (mode2 != 0)
80 cgit_tree_link(path2, NULL, NULL, cgit_query_head,
81 sha1_to_hex(new_rev_sha1), path2);
82 else
83 html_txt(path2);
73 } 84 }
74 html("</div>"); 85 html("</div>");
75} 86}
@@ -89,17 +100,16 @@ static void filepair_cb(struct diff_filepair *pair)
89 cgit_print_error("Error running diff"); 100 cgit_print_error("Error running diff");
90} 101}
91 102
92void cgit_print_diff(const char *new_rev, const char *old_rev) 103void cgit_print_diff(const char *new_rev, const char *old_rev, const char *prefix)
93{ 104{
94 unsigned char sha1[20], sha2[20];
95 enum object_type type; 105 enum object_type type;
96 unsigned long size; 106 unsigned long size;
97 struct commit *commit, *commit2; 107 struct commit *commit, *commit2;
98 108
99 if (!new_rev) 109 if (!new_rev)
100 new_rev = cgit_query_head; 110 new_rev = cgit_query_head;
101 get_sha1(new_rev, sha1); 111 get_sha1(new_rev, new_rev_sha1);
102 type = sha1_object_info(sha1, &size); 112 type = sha1_object_info(new_rev_sha1, &size);
103 if (type == OBJ_BAD) { 113 if (type == OBJ_BAD) {
104 cgit_print_error(fmt("Bad object name: %s", new_rev)); 114 cgit_print_error(fmt("Bad object name: %s", new_rev));
105 return; 115 return;
@@ -110,31 +120,30 @@ void cgit_print_diff(const char *new_rev, const char *old_rev)
110 return; 120 return;
111 } 121 }
112 122
113 commit = lookup_commit_reference(sha1); 123 commit = lookup_commit_reference(new_rev_sha1);
114 if (!commit || parse_commit(commit)) 124 if (!commit || parse_commit(commit))
115 cgit_print_error(fmt("Bad commit: %s", sha1_to_hex(sha1))); 125 cgit_print_error(fmt("Bad commit: %s", sha1_to_hex(new_rev_sha1)));
116 126
117 if (old_rev) 127 if (old_rev)
118 get_sha1(old_rev, sha2); 128 get_sha1(old_rev, old_rev_sha1);
119 else if (commit->parents && commit->parents->item) 129 else if (commit->parents && commit->parents->item)
120 hashcpy(sha2, commit->parents->item->object.sha1); 130 hashcpy(old_rev_sha1, commit->parents->item->object.sha1);
121 else 131 else
122 hashclr(sha2); 132 hashclr(old_rev_sha1);
123 133
124 if (!is_null_sha1(sha2)) { 134 if (!is_null_sha1(old_rev_sha1)) {
125 type = sha1_object_info(sha2, &size); 135 type = sha1_object_info(old_rev_sha1, &size);
126 if (type == OBJ_BAD) { 136 if (type == OBJ_BAD) {
127 cgit_print_error(fmt("Bad object name: %s", sha1_to_hex(sha2))); 137 cgit_print_error(fmt("Bad object name: %s", sha1_to_hex(old_rev_sha1)));
128 return; 138 return;
129 } 139 }
130 commit2 = lookup_commit_reference(sha2); 140 commit2 = lookup_commit_reference(old_rev_sha1);
131 if (!commit2 || parse_commit(commit2)) 141 if (!commit2 || parse_commit(commit2))
132 cgit_print_error(fmt("Bad commit: %s", sha1_to_hex(sha2))); 142 cgit_print_error(fmt("Bad commit: %s", sha1_to_hex(old_rev_sha1)));
133 } 143 }
134
135 html("<table class='diff'>"); 144 html("<table class='diff'>");
136 html("<tr><td>"); 145 html("<tr><td>");
137 cgit_diff_tree(sha2, sha1, filepair_cb); 146 cgit_diff_tree(old_rev_sha1, new_rev_sha1, filepair_cb, prefix);
138 html("</td></tr>"); 147 html("</td></tr>");
139 html("</table>"); 148 html("</table>");
140} 149}
diff --git a/ui-refs.c b/ui-refs.c new file mode 100644 index 0000000..295f5ba --- /dev/null +++ b/ui-refs.c
@@ -0,0 +1,30 @@
1/* ui-refs.c: browse symbolic refs
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
11
12
13
14void cgit_print_refs()
15{
16
17 html("<table class='list nowrap'>");
18
19 if (cgit_query_path && !strncmp(cgit_query_path, "heads", 5))
20 cgit_print_branches(0);
21 else if (cgit_query_path && !strncmp(cgit_query_path, "tags", 4))
22 cgit_print_tags(0);
23 else {
24 cgit_print_branches(0);
25 html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>");
26 cgit_print_tags(0);
27 }
28
29 html("</table>");
30}
diff --git a/ui-shared.c b/ui-shared.c index 5c5bcf3..e4bb98f 100644 --- a/ui-shared.c +++ b/ui-shared.c
@@ -227,6 +227,12 @@ void cgit_commit_link(char *name, char *title, char *class, char *head,
227 reporevlink("commit", name, title, class, head, rev, NULL); 227 reporevlink("commit", name, title, class, head, rev, NULL);
228} 228}
229 229
230void cgit_refs_link(char *name, char *title, char *class, char *head,
231 char *rev, char *path)
232{
233 reporevlink("refs", name, title, class, head, rev, path);
234}
235
230void cgit_snapshot_link(char *name, char *title, char *class, char *head, 236void cgit_snapshot_link(char *name, char *title, char *class, char *head,
231 char *rev, char *archivename) 237 char *rev, char *archivename)
232{ 238{
diff --git a/ui-summary.c b/ui-summary.c index de8a180..178e959 100644 --- a/ui-summary.c +++ b/ui-summary.c
@@ -10,40 +10,60 @@
10 10
11static int header; 11static int header;
12 12
13static int cgit_print_branch_cb(const char *refname, const unsigned char *sha1, 13static int cmp_age(int age1, int age2)
14 int flags, void *cb_data)
15{ 14{
16 struct commit *commit; 15 if (age1 != 0 && age2 != 0)
17 struct commitinfo *info; 16 return age2 - age1;
18 char buf[256]; 17
19 char *ref; 18 if (age1 == 0 && age2 == 0)
20 19 return 0;
21 ref = xstrdup(refname); 20
22 strncpy(buf, refname, sizeof(buf)); 21 if (age1 == 0)
23 commit = lookup_commit(sha1); 22 return +1;
24 // object is not really parsed at this point, because of some fallout 23
25 // from previous calls to git functions in cgit_print_log() 24 return -1;
26 commit->object.parsed = 0; 25}
27 if (commit && !parse_commit(commit)){ 26
28 info = cgit_parse_commit(commit); 27static int cmp_ref_name(const void *a, const void *b)
29 html("<tr><td>"); 28{
30 cgit_log_link(ref, NULL, NULL, ref, NULL, NULL, 0); 29 struct refinfo *r1 = *(struct refinfo **)a;
31 html("</td><td>"); 30 struct refinfo *r2 = *(struct refinfo **)b;
32 cgit_print_age(commit->date, -1, NULL); 31
33 html("</td><td>"); 32 return strcmp(r1->refname, r2->refname);
34 html_txt(info->author); 33}
35 html("</td><td>"); 34
36 cgit_commit_link(info->subject, NULL, NULL, ref, NULL); 35static int cmp_branch_age(const void *a, const void *b)
37 html("</td></tr>\n"); 36{
38 cgit_free_commitinfo(info); 37 struct refinfo *r1 = *(struct refinfo **)a;
39 } else { 38 struct refinfo *r2 = *(struct refinfo **)b;
40 html("<tr><td>"); 39
41 html_txt(buf); 40 return cmp_age(r1->commit->committer_date, r2->commit->committer_date);
42 html("</td><td colspan='3'>"); 41}
43 htmlf("*** bad ref %s ***", sha1_to_hex(sha1)); 42
44 html("</td></tr>\n"); 43static int cmp_tag_age(const void *a, const void *b)
45 } 44{
46 free(ref); 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 int print_branch(struct refinfo *ref)
52{
53 struct commitinfo *info = ref->commit;
54 char *name = (char *)ref->refname;
55
56 if (!info)
57 return 1;
58 html("<tr><td>");
59 cgit_log_link(name, NULL, NULL, name, NULL, NULL, 0);
60 html("</td><td>");
61 cgit_print_age(info->commit->date, -1, NULL);
62 html("</td><td>");
63 html_txt(info->author);
64 html("</td><td>");
65 cgit_commit_link(info->subject, NULL, NULL, name, NULL);
66 html("</td></tr>\n");
47 return 0; 67 return 0;
48} 68}
49 69
@@ -56,29 +76,22 @@ static void print_tag_header()
56 header = 1; 76 header = 1;
57} 77}
58 78
59static int cgit_print_tag_cb(const char *refname, const unsigned char *sha1, 79static int print_tag(struct refinfo *ref)
60 int flags, void *cb_data)
61{ 80{
62 struct tag *tag; 81 struct tag *tag;
63 struct taginfo *info; 82 struct taginfo *info;
64 struct object *obj; 83 char *url, *name = (char *)ref->refname;
65 char buf[256], *url;
66 84
67 strncpy(buf, refname, sizeof(buf)); 85 if (ref->object->type == OBJ_TAG) {
68 obj = parse_object(sha1); 86 tag = (struct tag *)ref->object;
69 if (!obj) 87 info = ref->tag;
70 return 1; 88 if (!tag || !info)
71 if (obj->type == OBJ_TAG) { 89 return 1;
72 tag = lookup_tag(sha1);
73 if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag)))
74 return 2;
75 if (!header)
76 print_tag_header();
77 html("<tr><td>"); 90 html("<tr><td>");
78 url = cgit_pageurl(cgit_query_repo, "tag", 91 url = cgit_pageurl(cgit_query_repo, "tag",
79 fmt("id=%s", refname)); 92 fmt("id=%s", name));
80 html_link_open(url, NULL, NULL); 93 html_link_open(url, NULL, NULL);
81 html_txt(buf); 94 html_txt(name);
82 html_link_close(); 95 html_link_close();
83 html("</td><td>"); 96 html("</td><td>");
84 if (info->tagger_date > 0) 97 if (info->tagger_date > 0)
@@ -93,9 +106,9 @@ static int cgit_print_tag_cb(const char *refname, const unsigned char *sha1,
93 if (!header) 106 if (!header)
94 print_tag_header(); 107 print_tag_header();
95 html("<tr><td>"); 108 html("<tr><td>");
96 html_txt(buf); 109 html_txt(name);
97 html("</td><td colspan='2'/><td>"); 110 html("</td><td colspan='2'/><td>");
98 cgit_object_link(obj); 111 cgit_object_link(ref->object);
99 html("</td></tr>\n"); 112 html("</td></tr>\n");
100 } 113 }
101 return 0; 114 return 0;
@@ -142,19 +155,64 @@ static int cgit_print_archive_cb(const char *refname, const unsigned char *sha1,
142 return 0; 155 return 0;
143} 156}
144 157
145static void cgit_print_branches() 158static void print_refs_link(char *path)
146{ 159{
160 html("<tr class='nohover'><td colspan='4'>");
161 cgit_refs_link("[...]", NULL, NULL, cgit_query_head, NULL, path);
162 html("</td></tr>");
163}
164
165void cgit_print_branches(int maxcount)
166{
167 struct reflist list;
168 int i;
169
147 html("<tr class='nohover'><th class='left'>Branch</th>" 170 html("<tr class='nohover'><th class='left'>Branch</th>"
148 "<th class='left'>Idle</th>" 171 "<th class='left'>Idle</th>"
149 "<th class='left'>Author</th>" 172 "<th class='left'>Author</th>"
150 "<th class='left'>Head commit</th></tr>\n"); 173 "<th class='left'>Head commit</th></tr>\n");
151 for_each_branch_ref(cgit_print_branch_cb, NULL); 174
175 list.refs = NULL;
176 list.alloc = list.count = 0;
177 for_each_branch_ref(cgit_refs_cb, &list);
178
179 if (maxcount == 0 || maxcount > list.count)
180 maxcount = list.count;
181
182 if (maxcount < list.count) {
183 qsort(list.refs, list.count, sizeof(*list.refs), cmp_branch_age);
184 qsort(list.refs, maxcount, sizeof(*list.refs), cmp_ref_name);
185 }
186
187 for(i=0; i<maxcount; i++)
188 print_branch(list.refs[i]);
189
190 if (maxcount < list.count)
191 print_refs_link("heads");
152} 192}
153 193
154static void cgit_print_tags() 194void cgit_print_tags(int maxcount)
155{ 195{
196 struct reflist list;
197 int i;
198
156 header = 0; 199 header = 0;
157 for_each_tag_ref(cgit_print_tag_cb, NULL); 200 list.refs = NULL;
201 list.alloc = list.count = 0;
202 for_each_tag_ref(cgit_refs_cb, &list);
203 if (list.count == 0)
204 return;
205 qsort(list.refs, list.count, sizeof(*list.refs), cmp_tag_age);
206 if (!maxcount)
207 maxcount = list.count;
208 else if (maxcount > list.count)
209 maxcount = list.count;
210 print_tag_header();
211 for(i=0; i<maxcount; i++)
212 print_tag(list.refs[i]);
213
214 if (maxcount < list.count)
215 print_refs_link("tags");
158} 216}
159 217
160static void cgit_print_archives() 218static void cgit_print_archives()
@@ -182,8 +240,8 @@ void cgit_print_summary()
182 html("<table class='list nowrap'>"); 240 html("<table class='list nowrap'>");
183 if (cgit_summary_log > 0) 241 if (cgit_summary_log > 0)
184 html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>"); 242 html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>");
185 cgit_print_branches(); 243 cgit_print_branches(cgit_summary_branches);
186 html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>"); 244 html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>");
187 cgit_print_tags(); 245 cgit_print_tags(cgit_summary_tags);
188 html("</table>"); 246 html("</table>");
189} 247}