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