author | Lars Hjemli <hjemli@gmail.com> | 2007-10-27 08:13:42 (UTC) |
---|---|---|
committer | Lars Hjemli <hjemli@gmail.com> | 2007-10-27 08:53:27 (UTC) |
commit | 763a6a09deec7290365a0072d25630daa7b417e2 (patch) (unidiff) | |
tree | d882b72c05ef2b798883e637cba3f53ece12d78c | |
parent | f6310fec783d2721ef61815a0eec525d6a904452 (diff) | |
download | cgit-763a6a09deec7290365a0072d25630daa7b417e2.zip cgit-763a6a09deec7290365a0072d25630daa7b417e2.tar.gz cgit-763a6a09deec7290365a0072d25630daa7b417e2.tar.bz2 |
Add support for config param summary-branches
This parameter can be used to specify max number of branches to show
on the summary page (if not all branches will be displayed, the "most
idle" branches are the ones to be pruned). The default value for this
parameter is 0, which disables the pruning.
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
-rw-r--r-- | cgit.h | 1 | ||||
-rw-r--r-- | shared.c | 3 | ||||
-rw-r--r-- | ui-summary.c | 31 |
3 files changed, 32 insertions, 3 deletions
@@ -1,269 +1,270 @@ | |||
1 | #ifndef CGIT_H | 1 | #ifndef CGIT_H |
2 | #define CGIT_H | 2 | #define CGIT_H |
3 | 3 | ||
4 | 4 | ||
5 | #include <git-compat-util.h> | 5 | #include <git-compat-util.h> |
6 | #include <cache.h> | 6 | #include <cache.h> |
7 | #include <grep.h> | 7 | #include <grep.h> |
8 | #include <object.h> | 8 | #include <object.h> |
9 | #include <tree.h> | 9 | #include <tree.h> |
10 | #include <commit.h> | 10 | #include <commit.h> |
11 | #include <tag.h> | 11 | #include <tag.h> |
12 | #include <diff.h> | 12 | #include <diff.h> |
13 | #include <diffcore.h> | 13 | #include <diffcore.h> |
14 | #include <refs.h> | 14 | #include <refs.h> |
15 | #include <revision.h> | 15 | #include <revision.h> |
16 | #include <log-tree.h> | 16 | #include <log-tree.h> |
17 | #include <archive.h> | 17 | #include <archive.h> |
18 | #include <xdiff/xdiff.h> | 18 | #include <xdiff/xdiff.h> |
19 | 19 | ||
20 | 20 | ||
21 | /* | 21 | /* |
22 | * The valid cgit repo-commands | 22 | * The valid cgit repo-commands |
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 | 31 | ||
32 | /* | 32 | /* |
33 | * Dateformats used on misc. pages | 33 | * Dateformats used on misc. pages |
34 | */ | 34 | */ |
35 | #define FMT_LONGDATE "%Y-%m-%d %H:%M:%S" | 35 | #define FMT_LONGDATE "%Y-%m-%d %H:%M:%S" |
36 | #define FMT_SHORTDATE "%Y-%m-%d" | 36 | #define FMT_SHORTDATE "%Y-%m-%d" |
37 | 37 | ||
38 | 38 | ||
39 | /* | 39 | /* |
40 | * Limits used for relative dates | 40 | * Limits used for relative dates |
41 | */ | 41 | */ |
42 | #define TM_MIN 60 | 42 | #define TM_MIN 60 |
43 | #define TM_HOUR (TM_MIN * 60) | 43 | #define TM_HOUR (TM_MIN * 60) |
44 | #define TM_DAY (TM_HOUR * 24) | 44 | #define TM_DAY (TM_HOUR * 24) |
45 | #define TM_WEEK (TM_DAY * 7) | 45 | #define TM_WEEK (TM_DAY * 7) |
46 | #define TM_YEAR (TM_DAY * 365) | 46 | #define TM_YEAR (TM_DAY * 365) |
47 | #define TM_MONTH (TM_YEAR / 12.0) | 47 | #define TM_MONTH (TM_YEAR / 12.0) |
48 | 48 | ||
49 | 49 | ||
50 | typedef void (*configfn)(const char *name, const char *value); | 50 | typedef void (*configfn)(const char *name, const char *value); |
51 | typedef void (*filepair_fn)(struct diff_filepair *pair); | 51 | typedef void (*filepair_fn)(struct diff_filepair *pair); |
52 | typedef void (*linediff_fn)(char *line, int len); | 52 | typedef void (*linediff_fn)(char *line, int len); |
53 | 53 | ||
54 | struct cacheitem { | 54 | struct cacheitem { |
55 | char *name; | 55 | char *name; |
56 | struct stat st; | 56 | struct stat st; |
57 | int ttl; | 57 | int ttl; |
58 | int fd; | 58 | int fd; |
59 | }; | 59 | }; |
60 | 60 | ||
61 | struct repoinfo { | 61 | struct repoinfo { |
62 | char *url; | 62 | char *url; |
63 | char *name; | 63 | char *name; |
64 | char *path; | 64 | char *path; |
65 | char *desc; | 65 | char *desc; |
66 | char *owner; | 66 | char *owner; |
67 | char *defbranch; | 67 | char *defbranch; |
68 | char *group; | 68 | char *group; |
69 | char *module_link; | 69 | char *module_link; |
70 | char *readme; | 70 | char *readme; |
71 | int snapshots; | 71 | int snapshots; |
72 | int enable_log_filecount; | 72 | int enable_log_filecount; |
73 | int enable_log_linecount; | 73 | int enable_log_linecount; |
74 | }; | 74 | }; |
75 | 75 | ||
76 | struct repolist { | 76 | struct repolist { |
77 | int length; | 77 | int length; |
78 | int count; | 78 | int count; |
79 | struct repoinfo *repos; | 79 | struct repoinfo *repos; |
80 | }; | 80 | }; |
81 | 81 | ||
82 | struct commitinfo { | 82 | struct commitinfo { |
83 | struct commit *commit; | 83 | struct commit *commit; |
84 | char *author; | 84 | char *author; |
85 | char *author_email; | 85 | char *author_email; |
86 | unsigned long author_date; | 86 | unsigned long author_date; |
87 | char *committer; | 87 | char *committer; |
88 | char *committer_email; | 88 | char *committer_email; |
89 | unsigned long committer_date; | 89 | unsigned long committer_date; |
90 | char *subject; | 90 | char *subject; |
91 | char *msg; | 91 | char *msg; |
92 | }; | 92 | }; |
93 | 93 | ||
94 | struct taginfo { | 94 | struct taginfo { |
95 | char *tagger; | 95 | char *tagger; |
96 | char *tagger_email; | 96 | char *tagger_email; |
97 | int tagger_date; | 97 | int tagger_date; |
98 | char *msg; | 98 | char *msg; |
99 | }; | 99 | }; |
100 | 100 | ||
101 | struct refinfo { | 101 | struct refinfo { |
102 | const char *refname; | 102 | const char *refname; |
103 | struct object *object; | 103 | struct object *object; |
104 | union { | 104 | union { |
105 | struct taginfo *tag; | 105 | struct taginfo *tag; |
106 | struct commitinfo *commit; | 106 | struct commitinfo *commit; |
107 | }; | 107 | }; |
108 | }; | 108 | }; |
109 | 109 | ||
110 | struct reflist { | 110 | struct reflist { |
111 | struct refinfo **refs; | 111 | struct refinfo **refs; |
112 | int alloc; | 112 | int alloc; |
113 | int count; | 113 | int count; |
114 | }; | 114 | }; |
115 | 115 | ||
116 | extern const char *cgit_version; | 116 | extern const char *cgit_version; |
117 | 117 | ||
118 | extern struct repolist cgit_repolist; | 118 | extern struct repolist cgit_repolist; |
119 | extern struct repoinfo *cgit_repo; | 119 | extern struct repoinfo *cgit_repo; |
120 | extern int cgit_cmd; | 120 | extern int cgit_cmd; |
121 | 121 | ||
122 | extern char *cgit_root_title; | 122 | extern char *cgit_root_title; |
123 | extern char *cgit_css; | 123 | extern char *cgit_css; |
124 | extern char *cgit_logo; | 124 | extern char *cgit_logo; |
125 | extern char *cgit_index_header; | 125 | extern char *cgit_index_header; |
126 | extern char *cgit_logo_link; | 126 | extern char *cgit_logo_link; |
127 | extern char *cgit_module_link; | 127 | extern char *cgit_module_link; |
128 | extern char *cgit_agefile; | 128 | extern char *cgit_agefile; |
129 | extern char *cgit_virtual_root; | 129 | extern char *cgit_virtual_root; |
130 | extern char *cgit_script_name; | 130 | extern char *cgit_script_name; |
131 | extern char *cgit_cache_root; | 131 | extern char *cgit_cache_root; |
132 | extern char *cgit_repo_group; | 132 | extern char *cgit_repo_group; |
133 | 133 | ||
134 | extern int cgit_nocache; | 134 | extern int cgit_nocache; |
135 | extern int cgit_snapshots; | 135 | extern int cgit_snapshots; |
136 | extern int cgit_enable_index_links; | 136 | extern int cgit_enable_index_links; |
137 | extern int cgit_enable_log_filecount; | 137 | extern int cgit_enable_log_filecount; |
138 | extern int cgit_enable_log_linecount; | 138 | extern int cgit_enable_log_linecount; |
139 | extern int cgit_max_lock_attempts; | 139 | extern int cgit_max_lock_attempts; |
140 | extern int cgit_cache_root_ttl; | 140 | extern int cgit_cache_root_ttl; |
141 | extern int cgit_cache_repo_ttl; | 141 | extern int cgit_cache_repo_ttl; |
142 | extern int cgit_cache_dynamic_ttl; | 142 | extern int cgit_cache_dynamic_ttl; |
143 | extern int cgit_cache_static_ttl; | 143 | extern int cgit_cache_static_ttl; |
144 | extern int cgit_cache_max_create_time; | 144 | extern int cgit_cache_max_create_time; |
145 | extern int cgit_summary_log; | 145 | extern int cgit_summary_log; |
146 | extern int cgit_summary_tags; | 146 | extern int cgit_summary_tags; |
147 | extern int cgit_summary_branches; | ||
147 | 148 | ||
148 | extern int cgit_max_msg_len; | 149 | extern int cgit_max_msg_len; |
149 | extern int cgit_max_repodesc_len; | 150 | extern int cgit_max_repodesc_len; |
150 | extern int cgit_max_commit_count; | 151 | extern int cgit_max_commit_count; |
151 | 152 | ||
152 | extern int cgit_query_has_symref; | 153 | extern int cgit_query_has_symref; |
153 | extern int cgit_query_has_sha1; | 154 | extern int cgit_query_has_sha1; |
154 | 155 | ||
155 | extern char *cgit_querystring; | 156 | extern char *cgit_querystring; |
156 | extern char *cgit_query_repo; | 157 | extern char *cgit_query_repo; |
157 | extern char *cgit_query_page; | 158 | extern char *cgit_query_page; |
158 | extern char *cgit_query_search; | 159 | extern char *cgit_query_search; |
159 | extern char *cgit_query_head; | 160 | extern char *cgit_query_head; |
160 | extern char *cgit_query_sha1; | 161 | extern char *cgit_query_sha1; |
161 | extern char *cgit_query_sha2; | 162 | extern char *cgit_query_sha2; |
162 | extern char *cgit_query_path; | 163 | extern char *cgit_query_path; |
163 | extern char *cgit_query_name; | 164 | extern char *cgit_query_name; |
164 | extern int cgit_query_ofs; | 165 | extern int cgit_query_ofs; |
165 | 166 | ||
166 | extern int htmlfd; | 167 | extern int htmlfd; |
167 | 168 | ||
168 | extern int cgit_get_cmd_index(const char *cmd); | 169 | extern int cgit_get_cmd_index(const char *cmd); |
169 | extern struct repoinfo *cgit_get_repoinfo(const char *url); | 170 | extern struct repoinfo *cgit_get_repoinfo(const char *url); |
170 | extern void cgit_global_config_cb(const char *name, const char *value); | 171 | extern void cgit_global_config_cb(const char *name, const char *value); |
171 | extern void cgit_repo_config_cb(const char *name, const char *value); | 172 | extern void cgit_repo_config_cb(const char *name, const char *value); |
172 | extern void cgit_querystring_cb(const char *name, const char *value); | 173 | extern void cgit_querystring_cb(const char *name, const char *value); |
173 | 174 | ||
174 | extern int chk_zero(int result, char *msg); | 175 | extern int chk_zero(int result, char *msg); |
175 | extern int chk_positive(int result, char *msg); | 176 | extern int chk_positive(int result, char *msg); |
176 | extern int chk_non_negative(int result, char *msg); | 177 | extern int chk_non_negative(int result, char *msg); |
177 | 178 | ||
178 | extern int hextoint(char c); | 179 | extern int hextoint(char c); |
179 | extern char *trim_end(const char *str, char c); | 180 | extern char *trim_end(const char *str, char c); |
180 | 181 | ||
181 | extern void cgit_add_ref(struct reflist *list, struct refinfo *ref); | 182 | extern void cgit_add_ref(struct reflist *list, struct refinfo *ref); |
182 | extern int cgit_refs_cb(const char *refname, const unsigned char *sha1, | 183 | extern int cgit_refs_cb(const char *refname, const unsigned char *sha1, |
183 | int flags, void *cb_data); | 184 | int flags, void *cb_data); |
184 | 185 | ||
185 | extern void *cgit_free_commitinfo(struct commitinfo *info); | 186 | extern void *cgit_free_commitinfo(struct commitinfo *info); |
186 | 187 | ||
187 | extern int cgit_diff_files(const unsigned char *old_sha1, | 188 | extern int cgit_diff_files(const unsigned char *old_sha1, |
188 | const unsigned char *new_sha1, | 189 | const unsigned char *new_sha1, |
189 | linediff_fn fn); | 190 | linediff_fn fn); |
190 | 191 | ||
191 | extern void cgit_diff_tree(const unsigned char *old_sha1, | 192 | extern void cgit_diff_tree(const unsigned char *old_sha1, |
192 | const unsigned char *new_sha1, | 193 | const unsigned char *new_sha1, |
193 | filepair_fn fn, const char *prefix); | 194 | filepair_fn fn, const char *prefix); |
194 | 195 | ||
195 | extern void cgit_diff_commit(struct commit *commit, filepair_fn fn); | 196 | extern void cgit_diff_commit(struct commit *commit, filepair_fn fn); |
196 | 197 | ||
197 | extern char *fmt(const char *format,...); | 198 | extern char *fmt(const char *format,...); |
198 | 199 | ||
199 | extern void html(const char *txt); | 200 | extern void html(const char *txt); |
200 | extern void htmlf(const char *format,...); | 201 | extern void htmlf(const char *format,...); |
201 | extern void html_txt(char *txt); | 202 | extern void html_txt(char *txt); |
202 | extern void html_ntxt(int len, char *txt); | 203 | extern void html_ntxt(int len, char *txt); |
203 | extern void html_attr(char *txt); | 204 | extern void html_attr(char *txt); |
204 | extern void html_hidden(char *name, char *value); | 205 | extern void html_hidden(char *name, char *value); |
205 | extern void html_link_open(char *url, char *title, char *class); | 206 | extern void html_link_open(char *url, char *title, char *class); |
206 | extern void html_link_close(void); | 207 | extern void html_link_close(void); |
207 | extern void html_filemode(unsigned short mode); | 208 | extern void html_filemode(unsigned short mode); |
208 | extern int html_include(const char *filename); | 209 | extern int html_include(const char *filename); |
209 | 210 | ||
210 | extern int cgit_read_config(const char *filename, configfn fn); | 211 | extern int cgit_read_config(const char *filename, configfn fn); |
211 | extern int cgit_parse_query(char *txt, configfn fn); | 212 | extern int cgit_parse_query(char *txt, configfn fn); |
212 | extern struct commitinfo *cgit_parse_commit(struct commit *commit); | 213 | extern struct commitinfo *cgit_parse_commit(struct commit *commit); |
213 | extern struct taginfo *cgit_parse_tag(struct tag *tag); | 214 | extern struct taginfo *cgit_parse_tag(struct tag *tag); |
214 | extern void cgit_parse_url(const char *url); | 215 | extern void cgit_parse_url(const char *url); |
215 | 216 | ||
216 | extern char *cache_safe_filename(const char *unsafe); | 217 | extern char *cache_safe_filename(const char *unsafe); |
217 | extern int cache_lock(struct cacheitem *item); | 218 | extern int cache_lock(struct cacheitem *item); |
218 | extern int cache_unlock(struct cacheitem *item); | 219 | extern int cache_unlock(struct cacheitem *item); |
219 | extern int cache_cancel_lock(struct cacheitem *item); | 220 | extern int cache_cancel_lock(struct cacheitem *item); |
220 | extern int cache_exist(struct cacheitem *item); | 221 | extern int cache_exist(struct cacheitem *item); |
221 | extern int cache_expired(struct cacheitem *item); | 222 | extern int cache_expired(struct cacheitem *item); |
222 | 223 | ||
223 | extern char *cgit_repourl(const char *reponame); | 224 | extern char *cgit_repourl(const char *reponame); |
224 | extern char *cgit_fileurl(const char *reponame, const char *pagename, | 225 | extern char *cgit_fileurl(const char *reponame, const char *pagename, |
225 | const char *filename, const char *query); | 226 | const char *filename, const char *query); |
226 | extern char *cgit_pageurl(const char *reponame, const char *pagename, | 227 | extern char *cgit_pageurl(const char *reponame, const char *pagename, |
227 | const char *query); | 228 | const char *query); |
228 | 229 | ||
229 | extern const char *cgit_repobasename(const char *reponame); | 230 | extern const char *cgit_repobasename(const char *reponame); |
230 | 231 | ||
231 | extern void cgit_tree_link(char *name, char *title, char *class, char *head, | 232 | extern void cgit_tree_link(char *name, char *title, char *class, char *head, |
232 | char *rev, char *path); | 233 | char *rev, char *path); |
233 | extern void cgit_log_link(char *name, char *title, char *class, char *head, | 234 | extern void cgit_log_link(char *name, char *title, char *class, char *head, |
234 | char *rev, char *path, int ofs); | 235 | char *rev, char *path, int ofs); |
235 | extern void cgit_commit_link(char *name, char *title, char *class, char *head, | 236 | extern void cgit_commit_link(char *name, char *title, char *class, char *head, |
236 | char *rev); | 237 | char *rev); |
237 | extern void cgit_snapshot_link(char *name, char *title, char *class, | 238 | extern void cgit_snapshot_link(char *name, char *title, char *class, |
238 | char *head, char *rev, char *archivename); | 239 | char *head, char *rev, char *archivename); |
239 | extern void cgit_diff_link(char *name, char *title, char *class, char *head, | 240 | extern void cgit_diff_link(char *name, char *title, char *class, char *head, |
240 | char *new_rev, char *old_rev, char *path); | 241 | char *new_rev, char *old_rev, char *path); |
241 | 242 | ||
242 | extern void cgit_object_link(struct object *obj); | 243 | extern void cgit_object_link(struct object *obj); |
243 | 244 | ||
244 | extern void cgit_print_error(char *msg); | 245 | extern void cgit_print_error(char *msg); |
245 | extern void cgit_print_date(time_t secs, char *format); | 246 | extern void cgit_print_date(time_t secs, char *format); |
246 | extern void cgit_print_age(time_t t, time_t max_relative, char *format); | 247 | extern void cgit_print_age(time_t t, time_t max_relative, char *format); |
247 | extern void cgit_print_docstart(char *title, struct cacheitem *item); | 248 | extern void cgit_print_docstart(char *title, struct cacheitem *item); |
248 | extern void cgit_print_docend(); | 249 | extern void cgit_print_docend(); |
249 | extern void cgit_print_pageheader(char *title, int show_search); | 250 | extern void cgit_print_pageheader(char *title, int show_search); |
250 | extern void cgit_print_snapshot_start(const char *mimetype, | 251 | extern void cgit_print_snapshot_start(const char *mimetype, |
251 | const char *filename, | 252 | const char *filename, |
252 | struct cacheitem *item); | 253 | struct cacheitem *item); |
253 | 254 | ||
254 | extern void cgit_print_repolist(struct cacheitem *item); | 255 | extern void cgit_print_repolist(struct cacheitem *item); |
255 | extern void cgit_print_summary(); | 256 | extern void cgit_print_summary(); |
256 | extern void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *path, int pager); | 257 | extern void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *path, int pager); |
257 | extern void cgit_print_blob(struct cacheitem *item, const char *hex, char *path); | 258 | extern void cgit_print_blob(struct cacheitem *item, const char *hex, char *path); |
258 | extern void cgit_print_tree(const char *rev, char *path); | 259 | extern void cgit_print_tree(const char *rev, char *path); |
259 | extern void cgit_print_commit(char *hex); | 260 | extern void cgit_print_commit(char *hex); |
260 | extern void cgit_print_tag(char *revname); | 261 | extern void cgit_print_tag(char *revname); |
261 | extern void cgit_print_diff(const char *new_hex, const char *old_hex, const char *prefix); | 262 | extern void cgit_print_diff(const char *new_hex, const char *old_hex, const char *prefix); |
262 | extern void cgit_print_snapshot(struct cacheitem *item, const char *head, | 263 | extern void cgit_print_snapshot(struct cacheitem *item, const char *head, |
263 | const char *hex, const char *prefix, | 264 | const char *hex, const char *prefix, |
264 | const char *filename, int snapshot); | 265 | const char *filename, int snapshot); |
265 | extern void cgit_print_snapshot_links(const char *repo, const char *head, | 266 | extern void cgit_print_snapshot_links(const char *repo, const char *head, |
266 | const char *hex, int snapshots); | 267 | const char *hex, int snapshots); |
267 | extern int cgit_parse_snapshots_mask(const char *str); | 268 | extern int cgit_parse_snapshots_mask(const char *str); |
268 | 269 | ||
269 | #endif /* CGIT_H */ | 270 | #endif /* CGIT_H */ |
@@ -1,469 +1,472 @@ | |||
1 | /* shared.c: global vars + some callback functions | 1 | /* shared.c: global vars + some callback functions |
2 | * | 2 | * |
3 | * Copyright (C) 2006 Lars Hjemli | 3 | * Copyright (C) 2006 Lars Hjemli |
4 | * | 4 | * |
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 | ||
11 | struct repolist cgit_repolist; | 11 | struct repolist cgit_repolist; |
12 | struct repoinfo *cgit_repo; | 12 | struct repoinfo *cgit_repo; |
13 | int cgit_cmd; | 13 | int cgit_cmd; |
14 | 14 | ||
15 | const char *cgit_version = CGIT_VERSION; | 15 | const char *cgit_version = CGIT_VERSION; |
16 | 16 | ||
17 | char *cgit_root_title = "Git repository browser"; | 17 | char *cgit_root_title = "Git repository browser"; |
18 | char *cgit_css = "/cgit.css"; | 18 | char *cgit_css = "/cgit.css"; |
19 | char *cgit_logo = "/git-logo.png"; | 19 | char *cgit_logo = "/git-logo.png"; |
20 | char *cgit_index_header = NULL; | 20 | char *cgit_index_header = NULL; |
21 | char *cgit_logo_link = "http://www.kernel.org/pub/software/scm/git/docs/"; | 21 | char *cgit_logo_link = "http://www.kernel.org/pub/software/scm/git/docs/"; |
22 | char *cgit_module_link = "./?repo=%s&page=commit&id=%s"; | 22 | char *cgit_module_link = "./?repo=%s&page=commit&id=%s"; |
23 | char *cgit_agefile = "info/web/last-modified"; | 23 | char *cgit_agefile = "info/web/last-modified"; |
24 | char *cgit_virtual_root = NULL; | 24 | char *cgit_virtual_root = NULL; |
25 | char *cgit_script_name = CGIT_SCRIPT_NAME; | 25 | char *cgit_script_name = CGIT_SCRIPT_NAME; |
26 | char *cgit_cache_root = CGIT_CACHE_ROOT; | 26 | char *cgit_cache_root = CGIT_CACHE_ROOT; |
27 | char *cgit_repo_group = NULL; | 27 | char *cgit_repo_group = NULL; |
28 | 28 | ||
29 | int cgit_nocache = 0; | 29 | int cgit_nocache = 0; |
30 | int cgit_snapshots = 0; | 30 | int cgit_snapshots = 0; |
31 | int cgit_enable_index_links = 0; | 31 | int cgit_enable_index_links = 0; |
32 | int cgit_enable_log_filecount = 0; | 32 | int cgit_enable_log_filecount = 0; |
33 | int cgit_enable_log_linecount = 0; | 33 | int cgit_enable_log_linecount = 0; |
34 | int cgit_max_lock_attempts = 5; | 34 | int cgit_max_lock_attempts = 5; |
35 | int cgit_cache_root_ttl = 5; | 35 | int cgit_cache_root_ttl = 5; |
36 | int cgit_cache_repo_ttl = 5; | 36 | int cgit_cache_repo_ttl = 5; |
37 | int cgit_cache_dynamic_ttl = 5; | 37 | int cgit_cache_dynamic_ttl = 5; |
38 | int cgit_cache_static_ttl = -1; | 38 | int cgit_cache_static_ttl = -1; |
39 | int cgit_cache_max_create_time = 5; | 39 | int cgit_cache_max_create_time = 5; |
40 | int cgit_summary_log = 0; | 40 | int cgit_summary_log = 0; |
41 | int cgit_summary_tags = 0; | 41 | int cgit_summary_tags = 0; |
42 | int cgit_summary_branches = 0; | ||
42 | int cgit_renamelimit = -1; | 43 | int cgit_renamelimit = -1; |
43 | 44 | ||
44 | int cgit_max_msg_len = 60; | 45 | int cgit_max_msg_len = 60; |
45 | int cgit_max_repodesc_len = 60; | 46 | int cgit_max_repodesc_len = 60; |
46 | int cgit_max_commit_count = 50; | 47 | int cgit_max_commit_count = 50; |
47 | 48 | ||
48 | int cgit_query_has_symref = 0; | 49 | int cgit_query_has_symref = 0; |
49 | int cgit_query_has_sha1 = 0; | 50 | int cgit_query_has_sha1 = 0; |
50 | 51 | ||
51 | char *cgit_querystring = NULL; | 52 | char *cgit_querystring = NULL; |
52 | char *cgit_query_repo = NULL; | 53 | char *cgit_query_repo = NULL; |
53 | char *cgit_query_page = NULL; | 54 | char *cgit_query_page = NULL; |
54 | char *cgit_query_head = NULL; | 55 | char *cgit_query_head = NULL; |
55 | char *cgit_query_search = NULL; | 56 | char *cgit_query_search = NULL; |
56 | char *cgit_query_sha1 = NULL; | 57 | char *cgit_query_sha1 = NULL; |
57 | char *cgit_query_sha2 = NULL; | 58 | char *cgit_query_sha2 = NULL; |
58 | char *cgit_query_path = NULL; | 59 | char *cgit_query_path = NULL; |
59 | char *cgit_query_name = NULL; | 60 | char *cgit_query_name = NULL; |
60 | int cgit_query_ofs = 0; | 61 | int cgit_query_ofs = 0; |
61 | 62 | ||
62 | int htmlfd = 0; | 63 | int htmlfd = 0; |
63 | 64 | ||
64 | 65 | ||
65 | int cgit_get_cmd_index(const char *cmd) | 66 | int cgit_get_cmd_index(const char *cmd) |
66 | { | 67 | { |
67 | static char *cmds[] = {"log", "commit", "diff", "tree", "blob", | 68 | static char *cmds[] = {"log", "commit", "diff", "tree", "blob", |
68 | "snapshot", "tag", NULL}; | 69 | "snapshot", "tag", NULL}; |
69 | int i; | 70 | int i; |
70 | 71 | ||
71 | for(i = 0; cmds[i]; i++) | 72 | for(i = 0; cmds[i]; i++) |
72 | if (!strcmp(cmd, cmds[i])) | 73 | if (!strcmp(cmd, cmds[i])) |
73 | return i + 1; | 74 | return i + 1; |
74 | return 0; | 75 | return 0; |
75 | } | 76 | } |
76 | 77 | ||
77 | int chk_zero(int result, char *msg) | 78 | int chk_zero(int result, char *msg) |
78 | { | 79 | { |
79 | if (result != 0) | 80 | if (result != 0) |
80 | die("%s: %s", msg, strerror(errno)); | 81 | die("%s: %s", msg, strerror(errno)); |
81 | return result; | 82 | return result; |
82 | } | 83 | } |
83 | 84 | ||
84 | int chk_positive(int result, char *msg) | 85 | int chk_positive(int result, char *msg) |
85 | { | 86 | { |
86 | if (result <= 0) | 87 | if (result <= 0) |
87 | die("%s: %s", msg, strerror(errno)); | 88 | die("%s: %s", msg, strerror(errno)); |
88 | return result; | 89 | return result; |
89 | } | 90 | } |
90 | 91 | ||
91 | int chk_non_negative(int result, char *msg) | 92 | int chk_non_negative(int result, char *msg) |
92 | { | 93 | { |
93 | if (result < 0) | 94 | if (result < 0) |
94 | die("%s: %s",msg, strerror(errno)); | 95 | die("%s: %s",msg, strerror(errno)); |
95 | return result; | 96 | return result; |
96 | } | 97 | } |
97 | 98 | ||
98 | struct repoinfo *add_repo(const char *url) | 99 | struct repoinfo *add_repo(const char *url) |
99 | { | 100 | { |
100 | struct repoinfo *ret; | 101 | struct repoinfo *ret; |
101 | 102 | ||
102 | if (++cgit_repolist.count > cgit_repolist.length) { | 103 | if (++cgit_repolist.count > cgit_repolist.length) { |
103 | if (cgit_repolist.length == 0) | 104 | if (cgit_repolist.length == 0) |
104 | cgit_repolist.length = 8; | 105 | cgit_repolist.length = 8; |
105 | else | 106 | else |
106 | cgit_repolist.length *= 2; | 107 | cgit_repolist.length *= 2; |
107 | cgit_repolist.repos = xrealloc(cgit_repolist.repos, | 108 | cgit_repolist.repos = xrealloc(cgit_repolist.repos, |
108 | cgit_repolist.length * | 109 | cgit_repolist.length * |
109 | sizeof(struct repoinfo)); | 110 | sizeof(struct repoinfo)); |
110 | } | 111 | } |
111 | 112 | ||
112 | ret = &cgit_repolist.repos[cgit_repolist.count-1]; | 113 | ret = &cgit_repolist.repos[cgit_repolist.count-1]; |
113 | ret->url = trim_end(url, '/'); | 114 | ret->url = trim_end(url, '/'); |
114 | ret->name = ret->url; | 115 | ret->name = ret->url; |
115 | ret->path = NULL; | 116 | ret->path = NULL; |
116 | ret->desc = NULL; | 117 | ret->desc = NULL; |
117 | ret->owner = NULL; | 118 | ret->owner = NULL; |
118 | ret->group = cgit_repo_group; | 119 | ret->group = cgit_repo_group; |
119 | ret->defbranch = "master"; | 120 | ret->defbranch = "master"; |
120 | ret->snapshots = cgit_snapshots; | 121 | ret->snapshots = cgit_snapshots; |
121 | ret->enable_log_filecount = cgit_enable_log_filecount; | 122 | ret->enable_log_filecount = cgit_enable_log_filecount; |
122 | ret->enable_log_linecount = cgit_enable_log_linecount; | 123 | ret->enable_log_linecount = cgit_enable_log_linecount; |
123 | ret->module_link = cgit_module_link; | 124 | ret->module_link = cgit_module_link; |
124 | ret->readme = NULL; | 125 | ret->readme = NULL; |
125 | return ret; | 126 | return ret; |
126 | } | 127 | } |
127 | 128 | ||
128 | struct repoinfo *cgit_get_repoinfo(const char *url) | 129 | struct repoinfo *cgit_get_repoinfo(const char *url) |
129 | { | 130 | { |
130 | int i; | 131 | int i; |
131 | struct repoinfo *repo; | 132 | struct repoinfo *repo; |
132 | 133 | ||
133 | for (i=0; i<cgit_repolist.count; i++) { | 134 | for (i=0; i<cgit_repolist.count; i++) { |
134 | repo = &cgit_repolist.repos[i]; | 135 | repo = &cgit_repolist.repos[i]; |
135 | if (!strcmp(repo->url, url)) | 136 | if (!strcmp(repo->url, url)) |
136 | return repo; | 137 | return repo; |
137 | } | 138 | } |
138 | return NULL; | 139 | return NULL; |
139 | } | 140 | } |
140 | 141 | ||
141 | void cgit_global_config_cb(const char *name, const char *value) | 142 | void cgit_global_config_cb(const char *name, const char *value) |
142 | { | 143 | { |
143 | if (!strcmp(name, "root-title")) | 144 | if (!strcmp(name, "root-title")) |
144 | cgit_root_title = xstrdup(value); | 145 | cgit_root_title = xstrdup(value); |
145 | else if (!strcmp(name, "css")) | 146 | else if (!strcmp(name, "css")) |
146 | cgit_css = xstrdup(value); | 147 | cgit_css = xstrdup(value); |
147 | else if (!strcmp(name, "logo")) | 148 | else if (!strcmp(name, "logo")) |
148 | cgit_logo = xstrdup(value); | 149 | cgit_logo = xstrdup(value); |
149 | else if (!strcmp(name, "index-header")) | 150 | else if (!strcmp(name, "index-header")) |
150 | cgit_index_header = xstrdup(value); | 151 | cgit_index_header = xstrdup(value); |
151 | else if (!strcmp(name, "logo-link")) | 152 | else if (!strcmp(name, "logo-link")) |
152 | cgit_logo_link = xstrdup(value); | 153 | cgit_logo_link = xstrdup(value); |
153 | else if (!strcmp(name, "module-link")) | 154 | else if (!strcmp(name, "module-link")) |
154 | cgit_module_link = xstrdup(value); | 155 | cgit_module_link = xstrdup(value); |
155 | else if (!strcmp(name, "virtual-root")) | 156 | else if (!strcmp(name, "virtual-root")) |
156 | cgit_virtual_root = trim_end(value, '/'); | 157 | cgit_virtual_root = trim_end(value, '/'); |
157 | else if (!strcmp(name, "nocache")) | 158 | else if (!strcmp(name, "nocache")) |
158 | cgit_nocache = atoi(value); | 159 | cgit_nocache = atoi(value); |
159 | else if (!strcmp(name, "snapshots")) | 160 | else if (!strcmp(name, "snapshots")) |
160 | cgit_snapshots = cgit_parse_snapshots_mask(value); | 161 | cgit_snapshots = cgit_parse_snapshots_mask(value); |
161 | else if (!strcmp(name, "enable-index-links")) | 162 | else if (!strcmp(name, "enable-index-links")) |
162 | cgit_enable_index_links = atoi(value); | 163 | cgit_enable_index_links = atoi(value); |
163 | else if (!strcmp(name, "enable-log-filecount")) | 164 | else if (!strcmp(name, "enable-log-filecount")) |
164 | cgit_enable_log_filecount = atoi(value); | 165 | cgit_enable_log_filecount = atoi(value); |
165 | else if (!strcmp(name, "enable-log-linecount")) | 166 | else if (!strcmp(name, "enable-log-linecount")) |
166 | cgit_enable_log_linecount = atoi(value); | 167 | cgit_enable_log_linecount = atoi(value); |
167 | else if (!strcmp(name, "cache-root")) | 168 | else if (!strcmp(name, "cache-root")) |
168 | cgit_cache_root = xstrdup(value); | 169 | cgit_cache_root = xstrdup(value); |
169 | else if (!strcmp(name, "cache-root-ttl")) | 170 | else if (!strcmp(name, "cache-root-ttl")) |
170 | cgit_cache_root_ttl = atoi(value); | 171 | cgit_cache_root_ttl = atoi(value); |
171 | else if (!strcmp(name, "cache-repo-ttl")) | 172 | else if (!strcmp(name, "cache-repo-ttl")) |
172 | cgit_cache_repo_ttl = atoi(value); | 173 | cgit_cache_repo_ttl = atoi(value); |
173 | else if (!strcmp(name, "cache-static-ttl")) | 174 | else if (!strcmp(name, "cache-static-ttl")) |
174 | cgit_cache_static_ttl = atoi(value); | 175 | cgit_cache_static_ttl = atoi(value); |
175 | else if (!strcmp(name, "cache-dynamic-ttl")) | 176 | else if (!strcmp(name, "cache-dynamic-ttl")) |
176 | cgit_cache_dynamic_ttl = atoi(value); | 177 | cgit_cache_dynamic_ttl = atoi(value); |
177 | else if (!strcmp(name, "max-message-length")) | 178 | else if (!strcmp(name, "max-message-length")) |
178 | cgit_max_msg_len = atoi(value); | 179 | cgit_max_msg_len = atoi(value); |
179 | else if (!strcmp(name, "max-repodesc-length")) | 180 | else if (!strcmp(name, "max-repodesc-length")) |
180 | cgit_max_repodesc_len = atoi(value); | 181 | cgit_max_repodesc_len = atoi(value); |
181 | else if (!strcmp(name, "max-commit-count")) | 182 | else if (!strcmp(name, "max-commit-count")) |
182 | cgit_max_commit_count = atoi(value); | 183 | cgit_max_commit_count = atoi(value); |
183 | else if (!strcmp(name, "summary-log")) | 184 | else if (!strcmp(name, "summary-log")) |
184 | cgit_summary_log = atoi(value); | 185 | cgit_summary_log = atoi(value); |
186 | else if (!strcmp(name, "summary-branches")) | ||
187 | cgit_summary_branches = atoi(value); | ||
185 | else if (!strcmp(name, "summary-tags")) | 188 | else if (!strcmp(name, "summary-tags")) |
186 | cgit_summary_tags = atoi(value); | 189 | cgit_summary_tags = atoi(value); |
187 | else if (!strcmp(name, "agefile")) | 190 | else if (!strcmp(name, "agefile")) |
188 | cgit_agefile = xstrdup(value); | 191 | cgit_agefile = xstrdup(value); |
189 | else if (!strcmp(name, "renamelimit")) | 192 | else if (!strcmp(name, "renamelimit")) |
190 | cgit_renamelimit = atoi(value); | 193 | cgit_renamelimit = atoi(value); |
191 | else if (!strcmp(name, "repo.group")) | 194 | else if (!strcmp(name, "repo.group")) |
192 | cgit_repo_group = xstrdup(value); | 195 | cgit_repo_group = xstrdup(value); |
193 | else if (!strcmp(name, "repo.url")) | 196 | else if (!strcmp(name, "repo.url")) |
194 | cgit_repo = add_repo(value); | 197 | cgit_repo = add_repo(value); |
195 | else if (!strcmp(name, "repo.name")) | 198 | else if (!strcmp(name, "repo.name")) |
196 | cgit_repo->name = xstrdup(value); | 199 | cgit_repo->name = xstrdup(value); |
197 | else if (cgit_repo && !strcmp(name, "repo.path")) | 200 | else if (cgit_repo && !strcmp(name, "repo.path")) |
198 | cgit_repo->path = trim_end(value, '/'); | 201 | cgit_repo->path = trim_end(value, '/'); |
199 | else if (cgit_repo && !strcmp(name, "repo.desc")) | 202 | else if (cgit_repo && !strcmp(name, "repo.desc")) |
200 | cgit_repo->desc = xstrdup(value); | 203 | cgit_repo->desc = xstrdup(value); |
201 | else if (cgit_repo && !strcmp(name, "repo.owner")) | 204 | else if (cgit_repo && !strcmp(name, "repo.owner")) |
202 | cgit_repo->owner = xstrdup(value); | 205 | cgit_repo->owner = xstrdup(value); |
203 | else if (cgit_repo && !strcmp(name, "repo.defbranch")) | 206 | else if (cgit_repo && !strcmp(name, "repo.defbranch")) |
204 | cgit_repo->defbranch = xstrdup(value); | 207 | cgit_repo->defbranch = xstrdup(value); |
205 | else if (cgit_repo && !strcmp(name, "repo.snapshots")) | 208 | else if (cgit_repo && !strcmp(name, "repo.snapshots")) |
206 | cgit_repo->snapshots = cgit_snapshots & cgit_parse_snapshots_mask(value); /* XXX: &? */ | 209 | cgit_repo->snapshots = cgit_snapshots & cgit_parse_snapshots_mask(value); /* XXX: &? */ |
207 | else if (cgit_repo && !strcmp(name, "repo.enable-log-filecount")) | 210 | else if (cgit_repo && !strcmp(name, "repo.enable-log-filecount")) |
208 | cgit_repo->enable_log_filecount = cgit_enable_log_filecount * atoi(value); | 211 | cgit_repo->enable_log_filecount = cgit_enable_log_filecount * atoi(value); |
209 | else if (cgit_repo && !strcmp(name, "repo.enable-log-linecount")) | 212 | else if (cgit_repo && !strcmp(name, "repo.enable-log-linecount")) |
210 | cgit_repo->enable_log_linecount = cgit_enable_log_linecount * atoi(value); | 213 | cgit_repo->enable_log_linecount = cgit_enable_log_linecount * atoi(value); |
211 | else if (cgit_repo && !strcmp(name, "repo.module-link")) | 214 | else if (cgit_repo && !strcmp(name, "repo.module-link")) |
212 | cgit_repo->module_link= xstrdup(value); | 215 | cgit_repo->module_link= xstrdup(value); |
213 | else if (cgit_repo && !strcmp(name, "repo.readme") && value != NULL) { | 216 | else if (cgit_repo && !strcmp(name, "repo.readme") && value != NULL) { |
214 | if (*value == '/') | 217 | if (*value == '/') |
215 | cgit_repo->readme = xstrdup(value); | 218 | cgit_repo->readme = xstrdup(value); |
216 | else | 219 | else |
217 | cgit_repo->readme = xstrdup(fmt("%s/%s", cgit_repo->path, value)); | 220 | cgit_repo->readme = xstrdup(fmt("%s/%s", cgit_repo->path, value)); |
218 | } else if (!strcmp(name, "include")) | 221 | } else if (!strcmp(name, "include")) |
219 | cgit_read_config(value, cgit_global_config_cb); | 222 | cgit_read_config(value, cgit_global_config_cb); |
220 | } | 223 | } |
221 | 224 | ||
222 | void cgit_querystring_cb(const char *name, const char *value) | 225 | void cgit_querystring_cb(const char *name, const char *value) |
223 | { | 226 | { |
224 | if (!strcmp(name,"r")) { | 227 | if (!strcmp(name,"r")) { |
225 | cgit_query_repo = xstrdup(value); | 228 | cgit_query_repo = xstrdup(value); |
226 | cgit_repo = cgit_get_repoinfo(value); | 229 | cgit_repo = cgit_get_repoinfo(value); |
227 | } else if (!strcmp(name, "p")) { | 230 | } else if (!strcmp(name, "p")) { |
228 | cgit_query_page = xstrdup(value); | 231 | cgit_query_page = xstrdup(value); |
229 | cgit_cmd = cgit_get_cmd_index(value); | 232 | cgit_cmd = cgit_get_cmd_index(value); |
230 | } else if (!strcmp(name, "url")) { | 233 | } else if (!strcmp(name, "url")) { |
231 | cgit_parse_url(value); | 234 | cgit_parse_url(value); |
232 | } else if (!strcmp(name, "q")) { | 235 | } else if (!strcmp(name, "q")) { |
233 | cgit_query_search = xstrdup(value); | 236 | cgit_query_search = xstrdup(value); |
234 | } else if (!strcmp(name, "h")) { | 237 | } else if (!strcmp(name, "h")) { |
235 | cgit_query_head = xstrdup(value); | 238 | cgit_query_head = xstrdup(value); |
236 | cgit_query_has_symref = 1; | 239 | cgit_query_has_symref = 1; |
237 | } else if (!strcmp(name, "id")) { | 240 | } else if (!strcmp(name, "id")) { |
238 | cgit_query_sha1 = xstrdup(value); | 241 | cgit_query_sha1 = xstrdup(value); |
239 | cgit_query_has_sha1 = 1; | 242 | cgit_query_has_sha1 = 1; |
240 | } else if (!strcmp(name, "id2")) { | 243 | } else if (!strcmp(name, "id2")) { |
241 | cgit_query_sha2 = xstrdup(value); | 244 | cgit_query_sha2 = xstrdup(value); |
242 | cgit_query_has_sha1 = 1; | 245 | cgit_query_has_sha1 = 1; |
243 | } else if (!strcmp(name, "ofs")) { | 246 | } else if (!strcmp(name, "ofs")) { |
244 | cgit_query_ofs = atoi(value); | 247 | cgit_query_ofs = atoi(value); |
245 | } else if (!strcmp(name, "path")) { | 248 | } else if (!strcmp(name, "path")) { |
246 | cgit_query_path = trim_end(value, '/'); | 249 | cgit_query_path = trim_end(value, '/'); |
247 | } else if (!strcmp(name, "name")) { | 250 | } else if (!strcmp(name, "name")) { |
248 | cgit_query_name = xstrdup(value); | 251 | cgit_query_name = xstrdup(value); |
249 | } | 252 | } |
250 | } | 253 | } |
251 | 254 | ||
252 | void *cgit_free_commitinfo(struct commitinfo *info) | 255 | void *cgit_free_commitinfo(struct commitinfo *info) |
253 | { | 256 | { |
254 | free(info->author); | 257 | free(info->author); |
255 | free(info->author_email); | 258 | free(info->author_email); |
256 | free(info->committer); | 259 | free(info->committer); |
257 | free(info->committer_email); | 260 | free(info->committer_email); |
258 | free(info->subject); | 261 | free(info->subject); |
259 | free(info); | 262 | free(info); |
260 | return NULL; | 263 | return NULL; |
261 | } | 264 | } |
262 | 265 | ||
263 | int hextoint(char c) | 266 | int hextoint(char c) |
264 | { | 267 | { |
265 | if (c >= 'a' && c <= 'f') | 268 | if (c >= 'a' && c <= 'f') |
266 | return 10 + c - 'a'; | 269 | return 10 + c - 'a'; |
267 | else if (c >= 'A' && c <= 'F') | 270 | else if (c >= 'A' && c <= 'F') |
268 | return 10 + c - 'A'; | 271 | return 10 + c - 'A'; |
269 | else if (c >= '0' && c <= '9') | 272 | else if (c >= '0' && c <= '9') |
270 | return c - '0'; | 273 | return c - '0'; |
271 | else | 274 | else |
272 | return -1; | 275 | return -1; |
273 | } | 276 | } |
274 | 277 | ||
275 | char *trim_end(const char *str, char c) | 278 | char *trim_end(const char *str, char c) |
276 | { | 279 | { |
277 | int len; | 280 | int len; |
278 | char *s, *t; | 281 | char *s, *t; |
279 | 282 | ||
280 | if (str == NULL) | 283 | if (str == NULL) |
281 | return NULL; | 284 | return NULL; |
282 | t = (char *)str; | 285 | t = (char *)str; |
283 | len = strlen(t); | 286 | len = strlen(t); |
284 | while(len > 0 && t[len - 1] == c) | 287 | while(len > 0 && t[len - 1] == c) |
285 | len--; | 288 | len--; |
286 | 289 | ||
287 | if (len == 0) | 290 | if (len == 0) |
288 | return NULL; | 291 | return NULL; |
289 | 292 | ||
290 | c = t[len]; | 293 | c = t[len]; |
291 | t[len] = '\0'; | 294 | t[len] = '\0'; |
292 | s = xstrdup(t); | 295 | s = xstrdup(t); |
293 | t[len] = c; | 296 | t[len] = c; |
294 | return s; | 297 | return s; |
295 | } | 298 | } |
296 | 299 | ||
297 | void cgit_add_ref(struct reflist *list, struct refinfo *ref) | 300 | void cgit_add_ref(struct reflist *list, struct refinfo *ref) |
298 | { | 301 | { |
299 | size_t size; | 302 | size_t size; |
300 | 303 | ||
301 | if (list->count >= list->alloc) { | 304 | if (list->count >= list->alloc) { |
302 | list->alloc += (list->alloc ? list->alloc : 4); | 305 | list->alloc += (list->alloc ? list->alloc : 4); |
303 | size = list->alloc * sizeof(struct refinfo *); | 306 | size = list->alloc * sizeof(struct refinfo *); |
304 | list->refs = xrealloc(list->refs, size); | 307 | list->refs = xrealloc(list->refs, size); |
305 | } | 308 | } |
306 | list->refs[list->count++] = ref; | 309 | list->refs[list->count++] = ref; |
307 | } | 310 | } |
308 | 311 | ||
309 | struct refinfo *cgit_mk_refinfo(const char *refname, const unsigned char *sha1) | 312 | struct refinfo *cgit_mk_refinfo(const char *refname, const unsigned char *sha1) |
310 | { | 313 | { |
311 | struct refinfo *ref; | 314 | struct refinfo *ref; |
312 | 315 | ||
313 | ref = xmalloc(sizeof (struct refinfo)); | 316 | ref = xmalloc(sizeof (struct refinfo)); |
314 | ref->refname = xstrdup(refname); | 317 | ref->refname = xstrdup(refname); |
315 | ref->object = parse_object(sha1); | 318 | ref->object = parse_object(sha1); |
316 | switch (ref->object->type) { | 319 | switch (ref->object->type) { |
317 | case OBJ_TAG: | 320 | case OBJ_TAG: |
318 | ref->tag = cgit_parse_tag((struct tag *)ref->object); | 321 | ref->tag = cgit_parse_tag((struct tag *)ref->object); |
319 | break; | 322 | break; |
320 | case OBJ_COMMIT: | 323 | case OBJ_COMMIT: |
321 | ref->commit = cgit_parse_commit((struct commit *)ref->object); | 324 | ref->commit = cgit_parse_commit((struct commit *)ref->object); |
322 | break; | 325 | break; |
323 | } | 326 | } |
324 | return ref; | 327 | return ref; |
325 | } | 328 | } |
326 | 329 | ||
327 | int cgit_refs_cb(const char *refname, const unsigned char *sha1, int flags, | 330 | int cgit_refs_cb(const char *refname, const unsigned char *sha1, int flags, |
328 | void *cb_data) | 331 | void *cb_data) |
329 | { | 332 | { |
330 | struct reflist *list = (struct reflist *)cb_data; | 333 | struct reflist *list = (struct reflist *)cb_data; |
331 | struct refinfo *info = cgit_mk_refinfo(refname, sha1); | 334 | struct refinfo *info = cgit_mk_refinfo(refname, sha1); |
332 | 335 | ||
333 | if (info) | 336 | if (info) |
334 | cgit_add_ref(list, info); | 337 | cgit_add_ref(list, info); |
335 | return 0; | 338 | return 0; |
336 | } | 339 | } |
337 | 340 | ||
338 | void cgit_diff_tree_cb(struct diff_queue_struct *q, | 341 | void cgit_diff_tree_cb(struct diff_queue_struct *q, |
339 | struct diff_options *options, void *data) | 342 | struct diff_options *options, void *data) |
340 | { | 343 | { |
341 | int i; | 344 | int i; |
342 | 345 | ||
343 | for (i = 0; i < q->nr; i++) { | 346 | for (i = 0; i < q->nr; i++) { |
344 | if (q->queue[i]->status == 'U') | 347 | if (q->queue[i]->status == 'U') |
345 | continue; | 348 | continue; |
346 | ((filepair_fn)data)(q->queue[i]); | 349 | ((filepair_fn)data)(q->queue[i]); |
347 | } | 350 | } |
348 | } | 351 | } |
349 | 352 | ||
350 | static int load_mmfile(mmfile_t *file, const unsigned char *sha1) | 353 | static int load_mmfile(mmfile_t *file, const unsigned char *sha1) |
351 | { | 354 | { |
352 | enum object_type type; | 355 | enum object_type type; |
353 | 356 | ||
354 | if (is_null_sha1(sha1)) { | 357 | if (is_null_sha1(sha1)) { |
355 | file->ptr = (char *)""; | 358 | file->ptr = (char *)""; |
356 | file->size = 0; | 359 | file->size = 0; |
357 | } else { | 360 | } else { |
358 | file->ptr = read_sha1_file(sha1, &type, | 361 | file->ptr = read_sha1_file(sha1, &type, |
359 | (unsigned long *)&file->size); | 362 | (unsigned long *)&file->size); |
360 | } | 363 | } |
361 | return 1; | 364 | return 1; |
362 | } | 365 | } |
363 | 366 | ||
364 | /* | 367 | /* |
365 | * Receive diff-buffers from xdiff and concatenate them as | 368 | * Receive diff-buffers from xdiff and concatenate them as |
366 | * needed across multiple callbacks. | 369 | * needed across multiple callbacks. |
367 | * | 370 | * |
368 | * This is basically a copy of xdiff-interface.c/xdiff_outf(), | 371 | * This is basically a copy of xdiff-interface.c/xdiff_outf(), |
369 | * ripped from git and modified to use globals instead of | 372 | * ripped from git and modified to use globals instead of |
370 | * a special callback-struct. | 373 | * a special callback-struct. |
371 | */ | 374 | */ |
372 | char *diffbuf = NULL; | 375 | char *diffbuf = NULL; |
373 | int buflen = 0; | 376 | int buflen = 0; |
374 | 377 | ||
375 | int filediff_cb(void *priv, mmbuffer_t *mb, int nbuf) | 378 | int filediff_cb(void *priv, mmbuffer_t *mb, int nbuf) |
376 | { | 379 | { |
377 | int i; | 380 | int i; |
378 | 381 | ||
379 | for (i = 0; i < nbuf; i++) { | 382 | for (i = 0; i < nbuf; i++) { |
380 | if (mb[i].ptr[mb[i].size-1] != '\n') { | 383 | if (mb[i].ptr[mb[i].size-1] != '\n') { |
381 | /* Incomplete line */ | 384 | /* Incomplete line */ |
382 | diffbuf = xrealloc(diffbuf, buflen + mb[i].size); | 385 | diffbuf = xrealloc(diffbuf, buflen + mb[i].size); |
383 | memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size); | 386 | memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size); |
384 | buflen += mb[i].size; | 387 | buflen += mb[i].size; |
385 | continue; | 388 | continue; |
386 | } | 389 | } |
387 | 390 | ||
388 | /* we have a complete line */ | 391 | /* we have a complete line */ |
389 | if (!diffbuf) { | 392 | if (!diffbuf) { |
390 | ((linediff_fn)priv)(mb[i].ptr, mb[i].size); | 393 | ((linediff_fn)priv)(mb[i].ptr, mb[i].size); |
391 | continue; | 394 | continue; |
392 | } | 395 | } |
393 | diffbuf = xrealloc(diffbuf, buflen + mb[i].size); | 396 | diffbuf = xrealloc(diffbuf, buflen + mb[i].size); |
394 | memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size); | 397 | memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size); |
395 | ((linediff_fn)priv)(diffbuf, buflen + mb[i].size); | 398 | ((linediff_fn)priv)(diffbuf, buflen + mb[i].size); |
396 | free(diffbuf); | 399 | free(diffbuf); |
397 | diffbuf = NULL; | 400 | diffbuf = NULL; |
398 | buflen = 0; | 401 | buflen = 0; |
399 | } | 402 | } |
400 | if (diffbuf) { | 403 | if (diffbuf) { |
401 | ((linediff_fn)priv)(diffbuf, buflen); | 404 | ((linediff_fn)priv)(diffbuf, buflen); |
402 | free(diffbuf); | 405 | free(diffbuf); |
403 | diffbuf = NULL; | 406 | diffbuf = NULL; |
404 | buflen = 0; | 407 | buflen = 0; |
405 | } | 408 | } |
406 | return 0; | 409 | return 0; |
407 | } | 410 | } |
408 | 411 | ||
409 | int cgit_diff_files(const unsigned char *old_sha1, | 412 | int cgit_diff_files(const unsigned char *old_sha1, |
410 | const unsigned char *new_sha1, | 413 | const unsigned char *new_sha1, |
411 | linediff_fn fn) | 414 | linediff_fn fn) |
412 | { | 415 | { |
413 | mmfile_t file1, file2; | 416 | mmfile_t file1, file2; |
414 | xpparam_t diff_params; | 417 | xpparam_t diff_params; |
415 | xdemitconf_t emit_params; | 418 | xdemitconf_t emit_params; |
416 | xdemitcb_t emit_cb; | 419 | xdemitcb_t emit_cb; |
417 | 420 | ||
418 | if (!load_mmfile(&file1, old_sha1) || !load_mmfile(&file2, new_sha1)) | 421 | if (!load_mmfile(&file1, old_sha1) || !load_mmfile(&file2, new_sha1)) |
419 | return 1; | 422 | return 1; |
420 | 423 | ||
421 | diff_params.flags = XDF_NEED_MINIMAL; | 424 | diff_params.flags = XDF_NEED_MINIMAL; |
422 | emit_params.ctxlen = 3; | 425 | emit_params.ctxlen = 3; |
423 | emit_params.flags = XDL_EMIT_FUNCNAMES; | 426 | emit_params.flags = XDL_EMIT_FUNCNAMES; |
424 | emit_params.find_func = NULL; | 427 | emit_params.find_func = NULL; |
425 | emit_cb.outf = filediff_cb; | 428 | emit_cb.outf = filediff_cb; |
426 | emit_cb.priv = fn; | 429 | emit_cb.priv = fn; |
427 | xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb); | 430 | xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb); |
428 | return 0; | 431 | return 0; |
429 | } | 432 | } |
430 | 433 | ||
431 | void cgit_diff_tree(const unsigned char *old_sha1, | 434 | void cgit_diff_tree(const unsigned char *old_sha1, |
432 | const unsigned char *new_sha1, | 435 | const unsigned char *new_sha1, |
433 | filepair_fn fn, const char *prefix) | 436 | filepair_fn fn, const char *prefix) |
434 | { | 437 | { |
435 | struct diff_options opt; | 438 | struct diff_options opt; |
436 | int ret; | 439 | int ret; |
437 | int prefixlen; | 440 | int prefixlen; |
438 | 441 | ||
439 | diff_setup(&opt); | 442 | diff_setup(&opt); |
440 | opt.output_format = DIFF_FORMAT_CALLBACK; | 443 | opt.output_format = DIFF_FORMAT_CALLBACK; |
441 | opt.detect_rename = 1; | 444 | opt.detect_rename = 1; |
442 | opt.rename_limit = cgit_renamelimit; | 445 | opt.rename_limit = cgit_renamelimit; |
443 | opt.recursive = 1; | 446 | opt.recursive = 1; |
444 | opt.format_callback = cgit_diff_tree_cb; | 447 | opt.format_callback = cgit_diff_tree_cb; |
445 | opt.format_callback_data = fn; | 448 | opt.format_callback_data = fn; |
446 | if (prefix) { | 449 | if (prefix) { |
447 | opt.nr_paths = 1; | 450 | opt.nr_paths = 1; |
448 | opt.paths = &prefix; | 451 | opt.paths = &prefix; |
449 | prefixlen = strlen(prefix); | 452 | prefixlen = strlen(prefix); |
450 | opt.pathlens = &prefixlen; | 453 | opt.pathlens = &prefixlen; |
451 | } | 454 | } |
452 | diff_setup_done(&opt); | 455 | diff_setup_done(&opt); |
453 | 456 | ||
454 | if (old_sha1 && !is_null_sha1(old_sha1)) | 457 | if (old_sha1 && !is_null_sha1(old_sha1)) |
455 | ret = diff_tree_sha1(old_sha1, new_sha1, "", &opt); | 458 | ret = diff_tree_sha1(old_sha1, new_sha1, "", &opt); |
456 | else | 459 | else |
457 | ret = diff_root_tree_sha1(new_sha1, "", &opt); | 460 | ret = diff_root_tree_sha1(new_sha1, "", &opt); |
458 | diffcore_std(&opt); | 461 | diffcore_std(&opt); |
459 | diff_flush(&opt); | 462 | diff_flush(&opt); |
460 | } | 463 | } |
461 | 464 | ||
462 | void cgit_diff_commit(struct commit *commit, filepair_fn fn) | 465 | void cgit_diff_commit(struct commit *commit, filepair_fn fn) |
463 | { | 466 | { |
464 | unsigned char *old_sha1 = NULL; | 467 | unsigned char *old_sha1 = NULL; |
465 | 468 | ||
466 | if (commit->parents) | 469 | if (commit->parents) |
467 | old_sha1 = commit->parents->item->object.sha1; | 470 | old_sha1 = commit->parents->item->object.sha1; |
468 | cgit_diff_tree(old_sha1, commit->object.sha1, fn, NULL); | 471 | cgit_diff_tree(old_sha1, commit->object.sha1, fn, NULL); |
469 | } | 472 | } |
diff --git a/ui-summary.c b/ui-summary.c index 05170cc..df79d01 100644 --- a/ui-summary.c +++ b/ui-summary.c | |||
@@ -1,220 +1,245 @@ | |||
1 | /* ui-summary.c: functions for generating repo summary page | 1 | /* ui-summary.c: functions for generating repo summary page |
2 | * | 2 | * |
3 | * Copyright (C) 2006 Lars Hjemli | 3 | * Copyright (C) 2006 Lars Hjemli |
4 | * | 4 | * |
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 | ||
11 | static int header; | 11 | static int header; |
12 | 12 | ||
13 | static int cmp_age(int age1, int age2) | 13 | static int cmp_age(int age1, int age2) |
14 | { | 14 | { |
15 | if (age1 != 0 && age2 != 0) | 15 | if (age1 != 0 && age2 != 0) |
16 | return age2 - age1; | 16 | return age2 - age1; |
17 | 17 | ||
18 | if (age1 == 0 && age2 == 0) | 18 | if (age1 == 0 && age2 == 0) |
19 | return 0; | 19 | return 0; |
20 | 20 | ||
21 | if (age1 == 0) | 21 | if (age1 == 0) |
22 | return +1; | 22 | return +1; |
23 | 23 | ||
24 | return -1; | 24 | return -1; |
25 | } | 25 | } |
26 | 26 | ||
27 | static 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 | |||
35 | static 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 | |||
27 | static int cmp_tag_age(const void *a, const void *b) | 43 | static int cmp_tag_age(const void *a, const void *b) |
28 | { | 44 | { |
29 | struct refinfo *r1 = *(struct refinfo **)a; | 45 | struct refinfo *r1 = *(struct refinfo **)a; |
30 | struct refinfo *r2 = *(struct refinfo **)b; | 46 | struct refinfo *r2 = *(struct refinfo **)b; |
31 | 47 | ||
32 | return cmp_age(r1->tag->tagger_date, r2->tag->tagger_date); | 48 | return cmp_age(r1->tag->tagger_date, r2->tag->tagger_date); |
33 | } | 49 | } |
34 | 50 | ||
35 | static void cgit_print_branch(struct refinfo *ref) | 51 | static void cgit_print_branch(struct refinfo *ref) |
36 | { | 52 | { |
37 | struct commit *commit; | 53 | struct commit *commit; |
38 | struct commitinfo *info; | 54 | struct commitinfo *info; |
39 | char *name = (char *)ref->refname; | 55 | char *name = (char *)ref->refname; |
40 | 56 | ||
41 | commit = lookup_commit(ref->object->sha1); | 57 | commit = lookup_commit(ref->object->sha1); |
42 | // 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 |
43 | // from previous calls to git functions in cgit_print_log() | 59 | // from previous calls to git functions in cgit_print_log() |
44 | commit->object.parsed = 0; | 60 | commit->object.parsed = 0; |
45 | if (commit && !parse_commit(commit)){ | 61 | if (commit && !parse_commit(commit)){ |
46 | info = cgit_parse_commit(commit); | 62 | info = cgit_parse_commit(commit); |
47 | html("<tr><td>"); | 63 | html("<tr><td>"); |
48 | cgit_log_link(name, NULL, NULL, name, NULL, NULL, 0); | 64 | cgit_log_link(name, NULL, NULL, name, NULL, NULL, 0); |
49 | html("</td><td>"); | 65 | html("</td><td>"); |
50 | cgit_print_age(commit->date, -1, NULL); | 66 | cgit_print_age(commit->date, -1, NULL); |
51 | html("</td><td>"); | 67 | html("</td><td>"); |
52 | html_txt(info->author); | 68 | html_txt(info->author); |
53 | html("</td><td>"); | 69 | html("</td><td>"); |
54 | cgit_commit_link(info->subject, NULL, NULL, name, NULL); | 70 | cgit_commit_link(info->subject, NULL, NULL, name, NULL); |
55 | html("</td></tr>\n"); | 71 | html("</td></tr>\n"); |
56 | cgit_free_commitinfo(info); | 72 | cgit_free_commitinfo(info); |
57 | } else { | 73 | } else { |
58 | html("<tr><td>"); | 74 | html("<tr><td>"); |
59 | html_txt(name); | 75 | html_txt(name); |
60 | html("</td><td colspan='3'>"); | 76 | html("</td><td colspan='3'>"); |
61 | htmlf("*** bad ref %s ***", sha1_to_hex(ref->object->sha1)); | 77 | htmlf("*** bad ref %s ***", sha1_to_hex(ref->object->sha1)); |
62 | html("</td></tr>\n"); | 78 | html("</td></tr>\n"); |
63 | } | 79 | } |
64 | } | 80 | } |
65 | 81 | ||
66 | static void print_tag_header() | 82 | static void print_tag_header() |
67 | { | 83 | { |
68 | html("<tr class='nohover'><th class='left'>Tag</th>" | 84 | html("<tr class='nohover'><th class='left'>Tag</th>" |
69 | "<th class='left'>Age</th>" | 85 | "<th class='left'>Age</th>" |
70 | "<th class='left'>Author</th>" | 86 | "<th class='left'>Author</th>" |
71 | "<th class='left'>Reference</th></tr>\n"); | 87 | "<th class='left'>Reference</th></tr>\n"); |
72 | header = 1; | 88 | header = 1; |
73 | } | 89 | } |
74 | 90 | ||
75 | static int print_tag(struct refinfo *ref) | 91 | static int print_tag(struct refinfo *ref) |
76 | { | 92 | { |
77 | struct tag *tag; | 93 | struct tag *tag; |
78 | struct taginfo *info; | 94 | struct taginfo *info; |
79 | char *url, *name = (char *)ref->refname; | 95 | char *url, *name = (char *)ref->refname; |
80 | 96 | ||
81 | if (ref->object->type == OBJ_TAG) { | 97 | if (ref->object->type == OBJ_TAG) { |
82 | tag = lookup_tag(ref->object->sha1); | 98 | tag = lookup_tag(ref->object->sha1); |
83 | if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag))) | 99 | if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag))) |
84 | return 2; | 100 | return 2; |
85 | html("<tr><td>"); | 101 | html("<tr><td>"); |
86 | url = cgit_pageurl(cgit_query_repo, "tag", | 102 | url = cgit_pageurl(cgit_query_repo, "tag", |
87 | fmt("id=%s", name)); | 103 | fmt("id=%s", name)); |
88 | html_link_open(url, NULL, NULL); | 104 | html_link_open(url, NULL, NULL); |
89 | html_txt(name); | 105 | html_txt(name); |
90 | html_link_close(); | 106 | html_link_close(); |
91 | html("</td><td>"); | 107 | html("</td><td>"); |
92 | if (info->tagger_date > 0) | 108 | if (info->tagger_date > 0) |
93 | cgit_print_age(info->tagger_date, -1, NULL); | 109 | cgit_print_age(info->tagger_date, -1, NULL); |
94 | html("</td><td>"); | 110 | html("</td><td>"); |
95 | if (info->tagger) | 111 | if (info->tagger) |
96 | html(info->tagger); | 112 | html(info->tagger); |
97 | html("</td><td>"); | 113 | html("</td><td>"); |
98 | cgit_object_link(tag->tagged); | 114 | cgit_object_link(tag->tagged); |
99 | html("</td></tr>\n"); | 115 | html("</td></tr>\n"); |
100 | } else { | 116 | } else { |
101 | if (!header) | 117 | if (!header) |
102 | print_tag_header(); | 118 | print_tag_header(); |
103 | html("<tr><td>"); | 119 | html("<tr><td>"); |
104 | html_txt(name); | 120 | html_txt(name); |
105 | html("</td><td colspan='2'/><td>"); | 121 | html("</td><td colspan='2'/><td>"); |
106 | cgit_object_link(ref->object); | 122 | cgit_object_link(ref->object); |
107 | html("</td></tr>\n"); | 123 | html("</td></tr>\n"); |
108 | } | 124 | } |
109 | return 0; | 125 | return 0; |
110 | } | 126 | } |
111 | 127 | ||
112 | static int cgit_print_archive_cb(const char *refname, const unsigned char *sha1, | 128 | static int cgit_print_archive_cb(const char *refname, const unsigned char *sha1, |
113 | int flags, void *cb_data) | 129 | int flags, void *cb_data) |
114 | { | 130 | { |
115 | struct tag *tag; | 131 | struct tag *tag; |
116 | struct taginfo *info; | 132 | struct taginfo *info; |
117 | struct object *obj; | 133 | struct object *obj; |
118 | char buf[256], *url; | 134 | char buf[256], *url; |
119 | unsigned char fileid[20]; | 135 | unsigned char fileid[20]; |
120 | 136 | ||
121 | if (prefixcmp(refname, "refs/archives")) | 137 | if (prefixcmp(refname, "refs/archives")) |
122 | return 0; | 138 | return 0; |
123 | strncpy(buf, refname+14, sizeof(buf)); | 139 | strncpy(buf, refname+14, sizeof(buf)); |
124 | obj = parse_object(sha1); | 140 | obj = parse_object(sha1); |
125 | if (!obj) | 141 | if (!obj) |
126 | return 1; | 142 | return 1; |
127 | if (obj->type == OBJ_TAG) { | 143 | if (obj->type == OBJ_TAG) { |
128 | tag = lookup_tag(sha1); | 144 | tag = lookup_tag(sha1); |
129 | if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag))) | 145 | if (!tag || parse_tag(tag) || !(info = cgit_parse_tag(tag))) |
130 | return 0; | 146 | return 0; |
131 | hashcpy(fileid, tag->tagged->sha1); | 147 | hashcpy(fileid, tag->tagged->sha1); |
132 | } else if (obj->type != OBJ_BLOB) { | 148 | } else if (obj->type != OBJ_BLOB) { |
133 | return 0; | 149 | return 0; |
134 | } else { | 150 | } else { |
135 | hashcpy(fileid, sha1); | 151 | hashcpy(fileid, sha1); |
136 | } | 152 | } |
137 | if (!header) { | 153 | if (!header) { |
138 | html("<table id='downloads'>"); | 154 | html("<table id='downloads'>"); |
139 | html("<tr><th>Downloads</th></tr>"); | 155 | html("<tr><th>Downloads</th></tr>"); |
140 | header = 1; | 156 | header = 1; |
141 | } | 157 | } |
142 | html("<tr><td>"); | 158 | html("<tr><td>"); |
143 | url = cgit_pageurl(cgit_query_repo, "blob", | 159 | url = cgit_pageurl(cgit_query_repo, "blob", |
144 | fmt("id=%s&path=%s", sha1_to_hex(fileid), | 160 | fmt("id=%s&path=%s", sha1_to_hex(fileid), |
145 | buf)); | 161 | buf)); |
146 | html_link_open(url, NULL, NULL); | 162 | html_link_open(url, NULL, NULL); |
147 | html_txt(buf); | 163 | html_txt(buf); |
148 | html_link_close(); | 164 | html_link_close(); |
149 | html("</td></tr>"); | 165 | html("</td></tr>"); |
150 | return 0; | 166 | return 0; |
151 | } | 167 | } |
152 | 168 | ||
153 | static void cgit_print_branches() | 169 | static void cgit_print_branches(int maxcount) |
154 | { | 170 | { |
155 | struct reflist list; | 171 | struct reflist list; |
156 | int i; | 172 | int i; |
157 | 173 | ||
158 | html("<tr class='nohover'><th class='left'>Branch</th>" | 174 | html("<tr class='nohover'><th class='left'>Branch</th>" |
159 | "<th class='left'>Idle</th>" | 175 | "<th class='left'>Idle</th>" |
160 | "<th class='left'>Author</th>" | 176 | "<th class='left'>Author</th>" |
161 | "<th class='left'>Head commit</th></tr>\n"); | 177 | "<th class='left'>Head commit</th></tr>\n"); |
162 | 178 | ||
163 | list.refs = NULL; | 179 | list.refs = NULL; |
164 | list.alloc = list.count = 0; | 180 | list.alloc = list.count = 0; |
165 | for_each_branch_ref(cgit_refs_cb, &list); | 181 | for_each_branch_ref(cgit_refs_cb, &list); |
166 | for(i=0; i<list.count; i++) | 182 | |
183 | if (maxcount == 0 || maxcount > list.count) | ||
184 | maxcount = list.count; | ||
185 | |||
186 | if (maxcount < list.count) { | ||
187 | qsort(list.refs, list.count, sizeof(*list.refs), cmp_branch_age); | ||
188 | qsort(list.refs, maxcount, sizeof(*list.refs), cmp_ref_name); | ||
189 | } | ||
190 | |||
191 | for(i=0; i<maxcount; i++) | ||
167 | cgit_print_branch(list.refs[i]); | 192 | cgit_print_branch(list.refs[i]); |
168 | } | 193 | } |
169 | 194 | ||
170 | static void cgit_print_tags(int maxcount) | 195 | static void cgit_print_tags(int maxcount) |
171 | { | 196 | { |
172 | struct reflist list; | 197 | struct reflist list; |
173 | int i; | 198 | int i; |
174 | 199 | ||
175 | header = 0; | 200 | header = 0; |
176 | list.refs = NULL; | 201 | list.refs = NULL; |
177 | list.alloc = list.count = 0; | 202 | list.alloc = list.count = 0; |
178 | for_each_tag_ref(cgit_refs_cb, &list); | 203 | for_each_tag_ref(cgit_refs_cb, &list); |
179 | if (list.count == 0) | 204 | if (list.count == 0) |
180 | return; | 205 | return; |
181 | qsort(list.refs, list.count, sizeof(*list.refs), cmp_tag_age); | 206 | qsort(list.refs, list.count, sizeof(*list.refs), cmp_tag_age); |
182 | if (!maxcount) | 207 | if (!maxcount) |
183 | maxcount = list.count; | 208 | maxcount = list.count; |
184 | else if (maxcount > list.count) | 209 | else if (maxcount > list.count) |
185 | maxcount = list.count; | 210 | maxcount = list.count; |
186 | print_tag_header(); | 211 | print_tag_header(); |
187 | for(i=0; i<maxcount; i++) | 212 | for(i=0; i<maxcount; i++) |
188 | print_tag(list.refs[i]); | 213 | print_tag(list.refs[i]); |
189 | } | 214 | } |
190 | 215 | ||
191 | static void cgit_print_archives() | 216 | static void cgit_print_archives() |
192 | { | 217 | { |
193 | header = 0; | 218 | header = 0; |
194 | for_each_ref(cgit_print_archive_cb, NULL); | 219 | for_each_ref(cgit_print_archive_cb, NULL); |
195 | if (header) | 220 | if (header) |
196 | html("</table>"); | 221 | html("</table>"); |
197 | } | 222 | } |
198 | 223 | ||
199 | void cgit_print_summary() | 224 | void cgit_print_summary() |
200 | { | 225 | { |
201 | html("<div id='summary'>"); | 226 | html("<div id='summary'>"); |
202 | cgit_print_archives(); | 227 | cgit_print_archives(); |
203 | html("<h2>"); | 228 | html("<h2>"); |
204 | html_txt(cgit_repo->name); | 229 | html_txt(cgit_repo->name); |
205 | html(" - "); | 230 | html(" - "); |
206 | html_txt(cgit_repo->desc); | 231 | html_txt(cgit_repo->desc); |
207 | html("</h2>"); | 232 | html("</h2>"); |
208 | if (cgit_repo->readme) | 233 | if (cgit_repo->readme) |
209 | html_include(cgit_repo->readme); | 234 | html_include(cgit_repo->readme); |
210 | html("</div>"); | 235 | html("</div>"); |
211 | if (cgit_summary_log > 0) | 236 | if (cgit_summary_log > 0) |
212 | cgit_print_log(cgit_query_head, 0, cgit_summary_log, NULL, NULL, 0); | 237 | cgit_print_log(cgit_query_head, 0, cgit_summary_log, NULL, NULL, 0); |
213 | html("<table class='list nowrap'>"); | 238 | html("<table class='list nowrap'>"); |
214 | if (cgit_summary_log > 0) | 239 | if (cgit_summary_log > 0) |
215 | html("<tr class='nohover'><td colspan='4'> </td></tr>"); | 240 | html("<tr class='nohover'><td colspan='4'> </td></tr>"); |
216 | cgit_print_branches(); | 241 | cgit_print_branches(cgit_summary_branches); |
217 | html("<tr class='nohover'><td colspan='4'> </td></tr>"); | 242 | html("<tr class='nohover'><td colspan='4'> </td></tr>"); |
218 | cgit_print_tags(cgit_summary_tags); | 243 | cgit_print_tags(cgit_summary_tags); |
219 | html("</table>"); | 244 | html("</table>"); |
220 | } | 245 | } |