summaryrefslogtreecommitdiffabout
path: root/shared.c
authorLars Hjemli <hjemli@gmail.com>2007-10-27 08:13:42 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2007-10-27 08:53:27 (UTC)
commit763a6a09deec7290365a0072d25630daa7b417e2 (patch) (unidiff)
treed882b72c05ef2b798883e637cba3f53ece12d78c /shared.c
parentf6310fec783d2721ef61815a0eec525d6a904452 (diff)
downloadcgit-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>
Diffstat (limited to 'shared.c') (more/less context) (ignore whitespace changes)
-rw-r--r--shared.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/shared.c b/shared.c
index 7e5eaba..ff600db 100644
--- a/shared.c
+++ b/shared.c
@@ -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
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_summary_tags = 0;
42int cgit_summary_branches = 0;
42int cgit_renamelimit = -1; 43int cgit_renamelimit = -1;
43 44
44int cgit_max_msg_len = 60; 45int cgit_max_msg_len = 60;
45int cgit_max_repodesc_len = 60; 46int cgit_max_repodesc_len = 60;
46int cgit_max_commit_count = 50; 47int cgit_max_commit_count = 50;
47 48
48int cgit_query_has_symref = 0; 49int cgit_query_has_symref = 0;
49int cgit_query_has_sha1 = 0; 50int cgit_query_has_sha1 = 0;
50 51
51char *cgit_querystring = NULL; 52char *cgit_querystring = NULL;
52char *cgit_query_repo = NULL; 53char *cgit_query_repo = NULL;
53char *cgit_query_page = NULL; 54char *cgit_query_page = NULL;
54char *cgit_query_head = NULL; 55char *cgit_query_head = NULL;
55char *cgit_query_search = NULL; 56char *cgit_query_search = NULL;
56char *cgit_query_sha1 = NULL; 57char *cgit_query_sha1 = NULL;
57char *cgit_query_sha2 = NULL; 58char *cgit_query_sha2 = NULL;
58char *cgit_query_path = NULL; 59char *cgit_query_path = NULL;
59char *cgit_query_name = NULL; 60char *cgit_query_name = NULL;
60int cgit_query_ofs = 0; 61int cgit_query_ofs = 0;
61 62
62int htmlfd = 0; 63int htmlfd = 0;
63 64
64 65
65int cgit_get_cmd_index(const char *cmd) 66int 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
77int chk_zero(int result, char *msg) 78int 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
84int chk_positive(int result, char *msg) 85int 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
91int chk_non_negative(int result, char *msg) 92int 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
98struct repoinfo *add_repo(const char *url) 99struct 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
128struct repoinfo *cgit_get_repoinfo(const char *url) 129struct 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
141void cgit_global_config_cb(const char *name, const char *value) 142void 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
222void cgit_querystring_cb(const char *name, const char *value) 225void 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
252void *cgit_free_commitinfo(struct commitinfo *info) 255void *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
263int hextoint(char c) 266int 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
275char *trim_end(const char *str, char c) 278char *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
297void cgit_add_ref(struct reflist *list, struct refinfo *ref) 300void 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
309struct refinfo *cgit_mk_refinfo(const char *refname, const unsigned char *sha1) 312struct 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
327int cgit_refs_cb(const char *refname, const unsigned char *sha1, int flags, 330int 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
338void cgit_diff_tree_cb(struct diff_queue_struct *q, 341void 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
350static int load_mmfile(mmfile_t *file, const unsigned char *sha1) 353static 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 */
372char *diffbuf = NULL; 375char *diffbuf = NULL;
373int buflen = 0; 376int buflen = 0;
374 377
375int filediff_cb(void *priv, mmbuffer_t *mb, int nbuf) 378int 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
409int cgit_diff_files(const unsigned char *old_sha1, 412int 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
431void cgit_diff_tree(const unsigned char *old_sha1, 434void 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
462void cgit_diff_commit(struct commit *commit, filepair_fn fn) 465void 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}