summaryrefslogtreecommitdiffabout
authorLars Hjemli <hjemli@gmail.com>2007-10-27 08:55:10 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2007-10-27 08:55:10 (UTC)
commitdd0f27eb36e737261b57d6ebcbd9fe20e559470d (patch) (unidiff)
tree4729ecc84e0b24b044131546ff39bdd55a6cd9a6
parent47bae9f58d5ecae437767b8e7835b23ad1804d0b (diff)
parentac1f493b6bbc589327e9ba3303f112fcd323c6b6 (diff)
downloadcgit-dd0f27eb36e737261b57d6ebcbd9fe20e559470d.zip
cgit-dd0f27eb36e737261b57d6ebcbd9fe20e559470d.tar.gz
cgit-dd0f27eb36e737261b57d6ebcbd9fe20e559470d.tar.bz2
Merge branch 'filter-refs'
* filter-refs: Add links to the new refs page from summary page Add support for refs view Make cgit_print_branches()/cgit_print_tags() external Add descriptions of summary-branches and summary-tags to cgitrc Add support for config param summary-branches Move logic for age comparision from cmp_tag_age into cmp_age() Add support for config param summary-tags Sort tags by age Use reflist to print tag info Use reflist to print branch info Add functions and types for ref lists
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--Makefile2
-rw-r--r--cgit.c3
-rw-r--r--cgit.h27
-rw-r--r--cgitrc10
-rw-r--r--shared.c49
-rw-r--r--ui-refs.c30
-rw-r--r--ui-shared.c6
-rw-r--r--ui-summary.c139
8 files changed, 229 insertions, 37 deletions
diff --git a/Makefile b/Makefile
index 8e3da72..36b5ff6 100644
--- a/Makefile
+++ b/Makefile
@@ -11,17 +11,17 @@ GIT_URL = http://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.bz2
11# Let the user override the above settings. 11# Let the user override the above settings.
12# 12#
13-include cgit.conf 13-include cgit.conf
14 14
15 15
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
23 23
24all: cgit git 24all: cgit git
25 25
26VERSION: force-version 26VERSION: force-version
27 @./gen-version.sh "$(CGIT_VERSION)" 27 @./gen-version.sh "$(CGIT_VERSION)"
diff --git a/cgit.c b/cgit.c
index 1b85b15..cc18ed4 100644
--- a/cgit.c
+++ b/cgit.c
@@ -98,16 +98,19 @@ static void cgit_print_repo_page(struct cacheitem *item)
98 cgit_query_path, 1); 98 cgit_query_path, 1);
99 break; 99 break;
100 case CMD_TREE: 100 case CMD_TREE:
101 cgit_print_tree(cgit_query_sha1, cgit_query_path); 101 cgit_print_tree(cgit_query_sha1, cgit_query_path);
102 break; 102 break;
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, cgit_query_path); 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.h b/cgit.h
index e96311f..f8f0316 100644
--- a/cgit.h
+++ b/cgit.h
@@ -23,16 +23,17 @@
23 */ 23 */
24#define CMD_LOG 1 24#define CMD_LOG 1
25#define CMD_COMMIT 2 25#define CMD_COMMIT 2
26#define CMD_DIFF 3 26#define CMD_DIFF 3
27#define CMD_TREE 4 27#define CMD_TREE 4
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
34 */ 35 */
35#define FMT_LONGDATE "%Y-%m-%d %H:%M:%S" 36#define FMT_LONGDATE "%Y-%m-%d %H:%M:%S"
36#define FMT_SHORTDATE "%Y-%m-%d" 37#define FMT_SHORTDATE "%Y-%m-%d"
37 38
38 39
@@ -93,16 +94,31 @@ struct commitinfo {
93 94
94struct taginfo { 95struct taginfo {
95 char *tagger; 96 char *tagger;
96 char *tagger_email; 97 char *tagger_email;
97 int tagger_date; 98 int tagger_date;
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;
104extern struct repoinfo *cgit_repo; 120extern struct repoinfo *cgit_repo;
105extern int cgit_cmd; 121extern int cgit_cmd;
106 122
107extern char *cgit_root_title; 123extern char *cgit_root_title;
108extern char *cgit_css; 124extern char *cgit_css;
@@ -123,16 +139,18 @@ extern int cgit_enable_log_filecount;
123extern int cgit_enable_log_linecount; 139extern int cgit_enable_log_linecount;
124extern int cgit_max_lock_attempts; 140extern int cgit_max_lock_attempts;
125extern int cgit_cache_root_ttl; 141extern int cgit_cache_root_ttl;
126extern int cgit_cache_repo_ttl; 142extern int cgit_cache_repo_ttl;
127extern int cgit_cache_dynamic_ttl; 143extern 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;
134extern int cgit_max_commit_count; 152extern int cgit_max_commit_count;
135 153
136extern int cgit_query_has_symref; 154extern int cgit_query_has_symref;
137extern int cgit_query_has_sha1; 155extern int cgit_query_has_sha1;
138 156
@@ -157,16 +175,20 @@ extern void cgit_querystring_cb(const char *name, const char *value);
157 175
158extern int chk_zero(int result, char *msg); 176extern int chk_zero(int result, char *msg);
159extern int chk_positive(int result, char *msg); 177extern int chk_positive(int result, char *msg);
160extern int chk_non_negative(int result, char *msg); 178extern int chk_non_negative(int result, char *msg);
161 179
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,
168 const unsigned char *new_sha1, 190 const unsigned char *new_sha1,
169 linediff_fn fn); 191 linediff_fn fn);
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,
@@ -209,39 +231,44 @@ extern char *cgit_pageurl(const char *reponame, const char *pagename,
209extern const char *cgit_repobasename(const char *reponame); 231extern const char *cgit_repobasename(const char *reponame);
210 232
211extern void cgit_tree_link(char *name, char *title, char *class, char *head, 233extern void cgit_tree_link(char *name, char *title, char *class, char *head,
212 char *rev, char *path); 234 char *rev, char *path);
213extern void cgit_log_link(char *name, char *title, char *class, char *head, 235extern 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,
220 char *new_rev, char *old_rev, char *path); 244 char *new_rev, char *old_rev, char *path);
221 245
222extern void cgit_object_link(struct object *obj); 246extern void cgit_object_link(struct object *obj);
223 247
224extern void cgit_print_error(char *msg); 248extern void cgit_print_error(char *msg);
225extern void cgit_print_date(time_t secs, char *format); 249extern void cgit_print_date(time_t secs, char *format);
226extern void cgit_print_age(time_t t, time_t max_relative, char *format); 250extern void cgit_print_age(time_t t, time_t max_relative, char *format);
227extern void cgit_print_docstart(char *title, struct cacheitem *item); 251extern void cgit_print_docstart(char *title, struct cacheitem *item);
228extern void cgit_print_docend(); 252extern void cgit_print_docend();
229extern void cgit_print_pageheader(char *title, int show_search); 253extern 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();
236extern void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *path, int pager); 262extern void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *path, int pager);
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, const char *prefix); 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);
245extern void cgit_print_snapshot_links(const char *repo, const char *head, 272extern void cgit_print_snapshot_links(const char *repo, const char *head,
246 const char *hex, int snapshots); 273 const char *hex, int snapshots);
247extern int cgit_parse_snapshots_mask(const char *str); 274extern int cgit_parse_snapshots_mask(const char *str);
diff --git a/cgitrc b/cgitrc
index 796a62c..2b09e01 100644
--- a/cgitrc
+++ b/cgitrc
@@ -25,16 +25,26 @@
25#enable-log-linecount=0 25#enable-log-linecount=0
26 26
27 27
28## Enable/disable display of HEAD shortlog in summary view. Set it to maximum 28## Enable/disable display of HEAD shortlog in summary view. Set it to maximum
29## number of commits that should be displayed 29## number of commits that should be displayed
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).
36## The cgit repo on hjemli.net uses the the following command in it's 46## The cgit repo on hjemli.net uses the the following command in it's
37## post-receive hook to update the age-file: 47## post-receive hook to update the age-file:
38## git-for-each-ref --format="%(committerdate)" --sort=-committerdate \ 48## git-for-each-ref --format="%(committerdate)" --sort=-committerdate \
39## --count=1 > $GIT_DIR/info/web/last-modifie 49## --count=1 > $GIT_DIR/info/web/last-modifie
40## 50##
diff --git a/shared.c b/shared.c
index 3d4feea..7eb2b0e 100644
--- a/shared.c
+++ b/shared.c
@@ -33,16 +33,18 @@ int cgit_enable_log_filecount = 0;
33int cgit_enable_log_linecount = 0; 33int cgit_enable_log_linecount = 0;
34int cgit_max_lock_attempts = 5; 34int cgit_max_lock_attempts = 5;
35int cgit_cache_root_ttl = 5; 35int cgit_cache_root_ttl = 5;
36int cgit_cache_repo_ttl = 5; 36int cgit_cache_repo_ttl = 5;
37int cgit_cache_dynamic_ttl = 5; 37int 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;
41int cgit_renamelimit = -1; 43int cgit_renamelimit = -1;
42 44
43int cgit_max_msg_len = 60; 45int cgit_max_msg_len = 60;
44int cgit_max_repodesc_len = 60; 46int cgit_max_repodesc_len = 60;
45int cgit_max_commit_count = 50; 47int cgit_max_commit_count = 50;
46 48
47int cgit_query_has_symref = 0; 49int cgit_query_has_symref = 0;
48int cgit_query_has_sha1 = 0; 50int cgit_query_has_sha1 = 0;
@@ -59,17 +61,17 @@ char *cgit_query_name = NULL;
59int cgit_query_ofs = 0; 61int cgit_query_ofs = 0;
60 62
61int htmlfd = 0; 63int htmlfd = 0;
62 64
63 65
64int cgit_get_cmd_index(const char *cmd) 66int cgit_get_cmd_index(const char *cmd)
65{ 67{
66 static char *cmds[] = {"log", "commit", "diff", "tree", "blob", 68 static char *cmds[] = {"log", "commit", "diff", "tree", "blob",
67 "snapshot", "tag", NULL}; 69 "snapshot", "tag", "refs", NULL};
68 int i; 70 int i;
69 71
70 for(i = 0; cmds[i]; i++) 72 for(i = 0; cmds[i]; i++)
71 if (!strcmp(cmd, cmds[i])) 73 if (!strcmp(cmd, cmds[i]))
72 return i + 1; 74 return i + 1;
73 return 0; 75 return 0;
74} 76}
75 77
@@ -176,16 +178,20 @@ void cgit_global_config_cb(const char *name, const char *value)
176 else if (!strcmp(name, "max-message-length")) 178 else if (!strcmp(name, "max-message-length"))
177 cgit_max_msg_len = atoi(value); 179 cgit_max_msg_len = atoi(value);
178 else if (!strcmp(name, "max-repodesc-length")) 180 else if (!strcmp(name, "max-repodesc-length"))
179 cgit_max_repodesc_len = atoi(value); 181 cgit_max_repodesc_len = atoi(value);
180 else if (!strcmp(name, "max-commit-count")) 182 else if (!strcmp(name, "max-commit-count"))
181 cgit_max_commit_count = atoi(value); 183 cgit_max_commit_count = atoi(value);
182 else if (!strcmp(name, "summary-log")) 184 else if (!strcmp(name, "summary-log"))
183 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);
184 else if (!strcmp(name, "agefile")) 190 else if (!strcmp(name, "agefile"))
185 cgit_agefile = xstrdup(value); 191 cgit_agefile = xstrdup(value);
186 else if (!strcmp(name, "renamelimit")) 192 else if (!strcmp(name, "renamelimit"))
187 cgit_renamelimit = atoi(value); 193 cgit_renamelimit = atoi(value);
188 else if (!strcmp(name, "repo.group")) 194 else if (!strcmp(name, "repo.group"))
189 cgit_repo_group = xstrdup(value); 195 cgit_repo_group = xstrdup(value);
190 else if (!strcmp(name, "repo.url")) 196 else if (!strcmp(name, "repo.url"))
191 cgit_repo = add_repo(value); 197 cgit_repo = add_repo(value);
@@ -286,16 +292,57 @@ char *trim_end(const char *str, char c)
286 292
287 c = t[len]; 293 c = t[len];
288 t[len] = '\0'; 294 t[len] = '\0';
289 s = xstrdup(t); 295 s = xstrdup(t);
290 t[len] = c; 296 t[len] = c;
291 return s; 297 return s;
292} 298}
293 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
294void cgit_diff_tree_cb(struct diff_queue_struct *q, 341void cgit_diff_tree_cb(struct diff_queue_struct *q,
295 struct diff_options *options, void *data) 342 struct diff_options *options, void *data)
296{ 343{
297 int i; 344 int i;
298 345
299 for (i = 0; i < q->nr; i++) { 346 for (i = 0; i < q->nr; i++) {
300 if (q->queue[i]->status == 'U') 347 if (q->queue[i]->status == 'U')
301 continue; 348 continue;
diff --git a/ui-refs.c b/ui-refs.c
new file mode 100644
index 0000000..295f5ba
--- a/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
@@ -222,16 +222,22 @@ void cgit_commit_link(char *name, char *title, char *class, char *head,
222 name[cgit_max_msg_len] = '\0'; 222 name[cgit_max_msg_len] = '\0';
223 name[cgit_max_msg_len - 1] = '.'; 223 name[cgit_max_msg_len - 1] = '.';
224 name[cgit_max_msg_len - 2] = '.'; 224 name[cgit_max_msg_len - 2] = '.';
225 name[cgit_max_msg_len - 3] = '.'; 225 name[cgit_max_msg_len - 3] = '.';
226 } 226 }
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{
233 reporevlink("snapshot", name, title, class, head, rev, archivename); 239 reporevlink("snapshot", name, title, class, head, rev, archivename);
234} 240}
235 241
236void cgit_diff_link(char *name, char *title, char *class, char *head, 242void cgit_diff_link(char *name, char *title, char *class, char *head,
237 char *new_rev, char *old_rev, char *path) 243 char *new_rev, char *old_rev, char *path)
diff --git a/ui-summary.c b/ui-summary.c
index de8a180..016fea2 100644
--- a/ui-summary.c
+++ b/ui-summary.c
@@ -5,102 +5,126 @@
5 * Licensed under GNU General Public License v2 5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text) 6 * (see COPYING for full license text)
7 */ 7 */
8 8
9#include "cgit.h" 9#include "cgit.h"
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) 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)
15{ 52{
16 struct commit *commit; 53 struct commit *commit;
17 struct commitinfo *info; 54 struct commitinfo *info;
18 char buf[256]; 55 char *name = (char *)ref->refname;
19 char *ref;
20 56
21 ref = xstrdup(refname); 57 commit = lookup_commit(ref->object->sha1);
22 strncpy(buf, refname, sizeof(buf));
23 commit = lookup_commit(sha1);
24 // object is not really parsed at this point, because of some fallout 58 // object is not really parsed at this point, because of some fallout
25 // from previous calls to git functions in cgit_print_log() 59 // from previous calls to git functions in cgit_print_log()
26 commit->object.parsed = 0; 60 commit->object.parsed = 0;
27 if (commit && !parse_commit(commit)){ 61 if (commit && !parse_commit(commit)){
28 info = cgit_parse_commit(commit); 62 info = cgit_parse_commit(commit);
29 html("<tr><td>"); 63 html("<tr><td>");
30 cgit_log_link(ref, NULL, NULL, ref, NULL, NULL, 0); 64 cgit_log_link(name, NULL, NULL, name, NULL, NULL, 0);
31 html("</td><td>"); 65 html("</td><td>");
32 cgit_print_age(commit->date, -1, NULL); 66 cgit_print_age(commit->date, -1, NULL);
33 html("</td><td>"); 67 html("</td><td>");
34 html_txt(info->author); 68 html_txt(info->author);
35 html("</td><td>"); 69 html("</td><td>");
36 cgit_commit_link(info->subject, NULL, NULL, ref, NULL); 70 cgit_commit_link(info->subject, NULL, NULL, name, NULL);
37 html("</td></tr>\n"); 71 html("</td></tr>\n");
38 cgit_free_commitinfo(info); 72 cgit_free_commitinfo(info);
39 } else { 73 } else {
40 html("<tr><td>"); 74 html("<tr><td>");
41 html_txt(buf); 75 html_txt(name);
42 html("</td><td colspan='3'>"); 76 html("</td><td colspan='3'>");
43 htmlf("*** bad ref %s ***", sha1_to_hex(sha1)); 77 htmlf("*** bad ref %s ***", sha1_to_hex(ref->object->sha1));
44 html("</td></tr>\n"); 78 html("</td></tr>\n");
45 } 79 }
46 free(ref);
47 return 0;
48} 80}
49 81
50static void print_tag_header() 82static void print_tag_header()
51{ 83{
52 html("<tr class='nohover'><th class='left'>Tag</th>" 84 html("<tr class='nohover'><th class='left'>Tag</th>"
53 "<th class='left'>Age</th>" 85 "<th class='left'>Age</th>"
54 "<th class='left'>Author</th>" 86 "<th class='left'>Author</th>"
55 "<th class='left'>Reference</th></tr>\n"); 87 "<th class='left'>Reference</th></tr>\n");
56 header = 1; 88 header = 1;
57} 89}
58 90
59static int cgit_print_tag_cb(const char *refname, const unsigned char *sha1, 91static int print_tag(struct refinfo *ref)
60 int flags, void *cb_data)
61{ 92{
62 struct tag *tag; 93 struct tag *tag;
63 struct taginfo *info; 94 struct taginfo *info;
64 struct object *obj; 95 char *url, *name = (char *)ref->refname;
65 char buf[256], *url;
66 96
67 strncpy(buf, refname, sizeof(buf)); 97 if (ref->object->type == OBJ_TAG) {
68 obj = parse_object(sha1); 98 tag = lookup_tag(ref->object->sha1);
69 if (!obj)
70 return 1;
71 if (obj->type == OBJ_TAG) {
72 tag = lookup_tag(sha1);
73 if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag))) 99 if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag)))
74 return 2; 100 return 2;
75 if (!header)
76 print_tag_header();
77 html("<tr><td>"); 101 html("<tr><td>");
78 url = cgit_pageurl(cgit_query_repo, "tag", 102 url = cgit_pageurl(cgit_query_repo, "tag",
79 fmt("id=%s", refname)); 103 fmt("id=%s", name));
80 html_link_open(url, NULL, NULL); 104 html_link_open(url, NULL, NULL);
81 html_txt(buf); 105 html_txt(name);
82 html_link_close(); 106 html_link_close();
83 html("</td><td>"); 107 html("</td><td>");
84 if (info->tagger_date > 0) 108 if (info->tagger_date > 0)
85 cgit_print_age(info->tagger_date, -1, NULL); 109 cgit_print_age(info->tagger_date, -1, NULL);
86 html("</td><td>"); 110 html("</td><td>");
87 if (info->tagger) 111 if (info->tagger)
88 html(info->tagger); 112 html(info->tagger);
89 html("</td><td>"); 113 html("</td><td>");
90 cgit_object_link(tag->tagged); 114 cgit_object_link(tag->tagged);
91 html("</td></tr>\n"); 115 html("</td></tr>\n");
92 } else { 116 } else {
93 if (!header) 117 if (!header)
94 print_tag_header(); 118 print_tag_header();
95 html("<tr><td>"); 119 html("<tr><td>");
96 html_txt(buf); 120 html_txt(name);
97 html("</td><td colspan='2'/><td>"); 121 html("</td><td colspan='2'/><td>");
98 cgit_object_link(obj); 122 cgit_object_link(ref->object);
99 html("</td></tr>\n"); 123 html("</td></tr>\n");
100 } 124 }
101 return 0; 125 return 0;
102} 126}
103 127
104static int cgit_print_archive_cb(const char *refname, const unsigned char *sha1, 128static int cgit_print_archive_cb(const char *refname, const unsigned char *sha1,
105 int flags, void *cb_data) 129 int flags, void *cb_data)
106{ 130{
@@ -137,29 +161,74 @@ static int cgit_print_archive_cb(const char *refname, const unsigned char *sha1,
137 buf)); 161 buf));
138 html_link_open(url, NULL, NULL); 162 html_link_open(url, NULL, NULL);
139 html_txt(buf); 163 html_txt(buf);
140 html_link_close(); 164 html_link_close();
141 html("</td></tr>"); 165 html("</td></tr>");
142 return 0; 166 return 0;
143} 167}
144 168
145static void cgit_print_branches() 169static void print_refs_link(char *path)
146{ 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
147 html("<tr class='nohover'><th class='left'>Branch</th>" 181 html("<tr class='nohover'><th class='left'>Branch</th>"
148 "<th class='left'>Idle</th>" 182 "<th class='left'>Idle</th>"
149 "<th class='left'>Author</th>" 183 "<th class='left'>Author</th>"
150 "<th class='left'>Head commit</th></tr>\n"); 184 "<th class='left'>Head commit</th></tr>\n");
151 for_each_branch_ref(cgit_print_branch_cb, NULL); 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");
152} 203}
153 204
154static void cgit_print_tags() 205void cgit_print_tags(int maxcount)
155{ 206{
207 struct reflist list;
208 int i;
209
156 header = 0; 210 header = 0;
157 for_each_tag_ref(cgit_print_tag_cb, NULL); 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");
158} 227}
159 228
160static void cgit_print_archives() 229static void cgit_print_archives()
161{ 230{
162 header = 0; 231 header = 0;
163 for_each_ref(cgit_print_archive_cb, NULL); 232 for_each_ref(cgit_print_archive_cb, NULL);
164 if (header) 233 if (header)
165 html("</table>"); 234 html("</table>");
@@ -177,13 +246,13 @@ void cgit_print_summary()
177 if (cgit_repo->readme) 246 if (cgit_repo->readme)
178 html_include(cgit_repo->readme); 247 html_include(cgit_repo->readme);
179 html("</div>"); 248 html("</div>");
180 if (cgit_summary_log > 0) 249 if (cgit_summary_log > 0)
181 cgit_print_log(cgit_query_head, 0, cgit_summary_log, NULL, NULL, 0); 250 cgit_print_log(cgit_query_head, 0, cgit_summary_log, NULL, NULL, 0);
182 html("<table class='list nowrap'>"); 251 html("<table class='list nowrap'>");
183 if (cgit_summary_log > 0) 252 if (cgit_summary_log > 0)
184 html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>"); 253 html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>");
185 cgit_print_branches(); 254 cgit_print_branches(cgit_summary_branches);
186 html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>"); 255 html("<tr class='nohover'><td colspan='4'>&nbsp;</td></tr>");
187 cgit_print_tags(); 256 cgit_print_tags(cgit_summary_tags);
188 html("</table>"); 257 html("</table>");
189} 258}