summaryrefslogtreecommitdiffabout
path: root/shared.c
authorLars Hjemli <hjemli@gmail.com>2007-06-17 16:12:03 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2007-06-17 16:12:03 (UTC)
commit4a0be586662843382ecfa53af34a13b291312bc0 (patch) (unidiff)
tree01e0cd725fe249df3449bb089aad9f8d58081f89 /shared.c
parentfaaca447b071592c9a1e1f14b4d0d2a39b4c795a (diff)
downloadcgit-4a0be586662843382ecfa53af34a13b291312bc0.zip
cgit-4a0be586662843382ecfa53af34a13b291312bc0.tar.gz
cgit-4a0be586662843382ecfa53af34a13b291312bc0.tar.bz2
Add cgit_diff_link()
This adds a new function used to generate links to the diff page and uses it everywhere such links appear (expect for single files in the diffstat displayed on the commit page: this is now a link to the tree page). The updated diff-page now expects zero, one or two revision specifiers, in parameters head, id and id2. Id defaults to head unless otherwise specified, while head (as usual) defaults to repo.defbranch. If id2 isn't specified, it defaults to the first parent of id1. The most important change is of course that now all repo pages (summary, log, tree, commit and diff) has support for passing on the current branch and revision, i.e. the road is now open for a 'static' menu with links to all of these pages. Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (limited to 'shared.c') (more/less context) (ignore whitespace changes)
-rw-r--r--shared.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/shared.c b/shared.c
index c7cd8a5..f20fb5c 100644
--- a/shared.c
+++ b/shared.c
@@ -1,378 +1,378 @@
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
15char *cgit_root_title = "Git repository browser"; 15char *cgit_root_title = "Git repository browser";
16char *cgit_css = "/cgit.css"; 16char *cgit_css = "/cgit.css";
17char *cgit_logo = "/git-logo.png"; 17char *cgit_logo = "/git-logo.png";
18char *cgit_index_header = NULL; 18char *cgit_index_header = NULL;
19char *cgit_logo_link = "http://www.kernel.org/pub/software/scm/git/docs/"; 19char *cgit_logo_link = "http://www.kernel.org/pub/software/scm/git/docs/";
20char *cgit_module_link = "./?repo=%s&page=commit&id=%s"; 20char *cgit_module_link = "./?repo=%s&page=commit&id=%s";
21char *cgit_agefile = "info/web/last-modified"; 21char *cgit_agefile = "info/web/last-modified";
22char *cgit_virtual_root = NULL; 22char *cgit_virtual_root = NULL;
23char *cgit_script_name = CGIT_SCRIPT_NAME; 23char *cgit_script_name = CGIT_SCRIPT_NAME;
24char *cgit_cache_root = "/var/cache/cgit"; 24char *cgit_cache_root = "/var/cache/cgit";
25char *cgit_repo_group = NULL; 25char *cgit_repo_group = NULL;
26 26
27int cgit_nocache = 0; 27int cgit_nocache = 0;
28int cgit_snapshots = 0; 28int cgit_snapshots = 0;
29int cgit_enable_log_filecount = 0; 29int cgit_enable_log_filecount = 0;
30int cgit_enable_log_linecount = 0; 30int cgit_enable_log_linecount = 0;
31int cgit_max_lock_attempts = 5; 31int cgit_max_lock_attempts = 5;
32int cgit_cache_root_ttl = 5; 32int cgit_cache_root_ttl = 5;
33int cgit_cache_repo_ttl = 5; 33int cgit_cache_repo_ttl = 5;
34int cgit_cache_dynamic_ttl = 5; 34int cgit_cache_dynamic_ttl = 5;
35int cgit_cache_static_ttl = -1; 35int cgit_cache_static_ttl = -1;
36int cgit_cache_max_create_time = 5; 36int cgit_cache_max_create_time = 5;
37int cgit_summary_log = 0; 37int cgit_summary_log = 0;
38 38
39int cgit_max_msg_len = 60; 39int cgit_max_msg_len = 60;
40int cgit_max_repodesc_len = 60; 40int cgit_max_repodesc_len = 60;
41int cgit_max_commit_count = 50; 41int cgit_max_commit_count = 50;
42 42
43int cgit_query_has_symref = 0; 43int cgit_query_has_symref = 0;
44int cgit_query_has_sha1 = 0; 44int cgit_query_has_sha1 = 0;
45 45
46char *cgit_querystring = NULL; 46char *cgit_querystring = NULL;
47char *cgit_query_repo = NULL; 47char *cgit_query_repo = NULL;
48char *cgit_query_page = NULL; 48char *cgit_query_page = NULL;
49char *cgit_query_head = NULL; 49char *cgit_query_head = NULL;
50char *cgit_query_search = NULL; 50char *cgit_query_search = NULL;
51char *cgit_query_sha1 = NULL; 51char *cgit_query_sha1 = NULL;
52char *cgit_query_sha2 = NULL; 52char *cgit_query_sha2 = NULL;
53char *cgit_query_path = NULL; 53char *cgit_query_path = NULL;
54char *cgit_query_name = NULL; 54char *cgit_query_name = NULL;
55int cgit_query_ofs = 0; 55int cgit_query_ofs = 0;
56 56
57int htmlfd = 0; 57int htmlfd = 0;
58 58
59 59
60int cgit_get_cmd_index(const char *cmd) 60int cgit_get_cmd_index(const char *cmd)
61{ 61{
62 static char *cmds[] = {"log", "commit", "diff", "tree", "blob", 62 static char *cmds[] = {"log", "commit", "diff", "tree", "blob",
63 "snapshot", NULL}; 63 "snapshot", NULL};
64 int i; 64 int i;
65 65
66 for(i = 0; cmds[i]; i++) 66 for(i = 0; cmds[i]; i++)
67 if (!strcmp(cmd, cmds[i])) 67 if (!strcmp(cmd, cmds[i]))
68 return i + 1; 68 return i + 1;
69 return 0; 69 return 0;
70} 70}
71 71
72int chk_zero(int result, char *msg) 72int chk_zero(int result, char *msg)
73{ 73{
74 if (result != 0) 74 if (result != 0)
75 die("%s: %s", msg, strerror(errno)); 75 die("%s: %s", msg, strerror(errno));
76 return result; 76 return result;
77} 77}
78 78
79int chk_positive(int result, char *msg) 79int chk_positive(int result, char *msg)
80{ 80{
81 if (result <= 0) 81 if (result <= 0)
82 die("%s: %s", msg, strerror(errno)); 82 die("%s: %s", msg, strerror(errno));
83 return result; 83 return result;
84} 84}
85 85
86struct repoinfo *add_repo(const char *url) 86struct repoinfo *add_repo(const char *url)
87{ 87{
88 struct repoinfo *ret; 88 struct repoinfo *ret;
89 89
90 if (++cgit_repolist.count > cgit_repolist.length) { 90 if (++cgit_repolist.count > cgit_repolist.length) {
91 if (cgit_repolist.length == 0) 91 if (cgit_repolist.length == 0)
92 cgit_repolist.length = 8; 92 cgit_repolist.length = 8;
93 else 93 else
94 cgit_repolist.length *= 2; 94 cgit_repolist.length *= 2;
95 cgit_repolist.repos = xrealloc(cgit_repolist.repos, 95 cgit_repolist.repos = xrealloc(cgit_repolist.repos,
96 cgit_repolist.length * 96 cgit_repolist.length *
97 sizeof(struct repoinfo)); 97 sizeof(struct repoinfo));
98 } 98 }
99 99
100 ret = &cgit_repolist.repos[cgit_repolist.count-1]; 100 ret = &cgit_repolist.repos[cgit_repolist.count-1];
101 ret->url = xstrdup(url); 101 ret->url = xstrdup(url);
102 ret->name = ret->url; 102 ret->name = ret->url;
103 ret->path = NULL; 103 ret->path = NULL;
104 ret->desc = NULL; 104 ret->desc = NULL;
105 ret->owner = NULL; 105 ret->owner = NULL;
106 ret->group = cgit_repo_group; 106 ret->group = cgit_repo_group;
107 ret->defbranch = "master"; 107 ret->defbranch = "master";
108 ret->snapshots = cgit_snapshots; 108 ret->snapshots = cgit_snapshots;
109 ret->enable_log_filecount = cgit_enable_log_filecount; 109 ret->enable_log_filecount = cgit_enable_log_filecount;
110 ret->enable_log_linecount = cgit_enable_log_linecount; 110 ret->enable_log_linecount = cgit_enable_log_linecount;
111 ret->module_link = cgit_module_link; 111 ret->module_link = cgit_module_link;
112 ret->readme = NULL; 112 ret->readme = NULL;
113 return ret; 113 return ret;
114} 114}
115 115
116struct repoinfo *cgit_get_repoinfo(const char *url) 116struct repoinfo *cgit_get_repoinfo(const char *url)
117{ 117{
118 int i; 118 int i;
119 struct repoinfo *repo; 119 struct repoinfo *repo;
120 120
121 for (i=0; i<cgit_repolist.count; i++) { 121 for (i=0; i<cgit_repolist.count; i++) {
122 repo = &cgit_repolist.repos[i]; 122 repo = &cgit_repolist.repos[i];
123 if (!strcmp(repo->url, url)) 123 if (!strcmp(repo->url, url))
124 return repo; 124 return repo;
125 } 125 }
126 return NULL; 126 return NULL;
127} 127}
128 128
129void cgit_global_config_cb(const char *name, const char *value) 129void cgit_global_config_cb(const char *name, const char *value)
130{ 130{
131 if (!strcmp(name, "root-title")) 131 if (!strcmp(name, "root-title"))
132 cgit_root_title = xstrdup(value); 132 cgit_root_title = xstrdup(value);
133 else if (!strcmp(name, "css")) 133 else if (!strcmp(name, "css"))
134 cgit_css = xstrdup(value); 134 cgit_css = xstrdup(value);
135 else if (!strcmp(name, "logo")) 135 else if (!strcmp(name, "logo"))
136 cgit_logo = xstrdup(value); 136 cgit_logo = xstrdup(value);
137 else if (!strcmp(name, "index-header")) 137 else if (!strcmp(name, "index-header"))
138 cgit_index_header = xstrdup(value); 138 cgit_index_header = xstrdup(value);
139 else if (!strcmp(name, "logo-link")) 139 else if (!strcmp(name, "logo-link"))
140 cgit_logo_link = xstrdup(value); 140 cgit_logo_link = xstrdup(value);
141 else if (!strcmp(name, "module-link")) 141 else if (!strcmp(name, "module-link"))
142 cgit_module_link = xstrdup(value); 142 cgit_module_link = xstrdup(value);
143 else if (!strcmp(name, "virtual-root")) 143 else if (!strcmp(name, "virtual-root"))
144 cgit_virtual_root = xstrdup(value); 144 cgit_virtual_root = xstrdup(value);
145 else if (!strcmp(name, "nocache")) 145 else if (!strcmp(name, "nocache"))
146 cgit_nocache = atoi(value); 146 cgit_nocache = atoi(value);
147 else if (!strcmp(name, "snapshots")) 147 else if (!strcmp(name, "snapshots"))
148 cgit_snapshots = atoi(value); 148 cgit_snapshots = atoi(value);
149 else if (!strcmp(name, "enable-log-filecount")) 149 else if (!strcmp(name, "enable-log-filecount"))
150 cgit_enable_log_filecount = atoi(value); 150 cgit_enable_log_filecount = atoi(value);
151 else if (!strcmp(name, "enable-log-linecount")) 151 else if (!strcmp(name, "enable-log-linecount"))
152 cgit_enable_log_linecount = atoi(value); 152 cgit_enable_log_linecount = atoi(value);
153 else if (!strcmp(name, "cache-root")) 153 else if (!strcmp(name, "cache-root"))
154 cgit_cache_root = xstrdup(value); 154 cgit_cache_root = xstrdup(value);
155 else if (!strcmp(name, "cache-root-ttl")) 155 else if (!strcmp(name, "cache-root-ttl"))
156 cgit_cache_root_ttl = atoi(value); 156 cgit_cache_root_ttl = atoi(value);
157 else if (!strcmp(name, "cache-repo-ttl")) 157 else if (!strcmp(name, "cache-repo-ttl"))
158 cgit_cache_repo_ttl = atoi(value); 158 cgit_cache_repo_ttl = atoi(value);
159 else if (!strcmp(name, "cache-static-ttl")) 159 else if (!strcmp(name, "cache-static-ttl"))
160 cgit_cache_static_ttl = atoi(value); 160 cgit_cache_static_ttl = atoi(value);
161 else if (!strcmp(name, "cache-dynamic-ttl")) 161 else if (!strcmp(name, "cache-dynamic-ttl"))
162 cgit_cache_dynamic_ttl = atoi(value); 162 cgit_cache_dynamic_ttl = atoi(value);
163 else if (!strcmp(name, "max-message-length")) 163 else if (!strcmp(name, "max-message-length"))
164 cgit_max_msg_len = atoi(value); 164 cgit_max_msg_len = atoi(value);
165 else if (!strcmp(name, "max-repodesc-length")) 165 else if (!strcmp(name, "max-repodesc-length"))
166 cgit_max_repodesc_len = atoi(value); 166 cgit_max_repodesc_len = atoi(value);
167 else if (!strcmp(name, "max-commit-count")) 167 else if (!strcmp(name, "max-commit-count"))
168 cgit_max_commit_count = atoi(value); 168 cgit_max_commit_count = atoi(value);
169 else if (!strcmp(name, "summary-log")) 169 else if (!strcmp(name, "summary-log"))
170 cgit_summary_log = atoi(value); 170 cgit_summary_log = atoi(value);
171 else if (!strcmp(name, "agefile")) 171 else if (!strcmp(name, "agefile"))
172 cgit_agefile = xstrdup(value); 172 cgit_agefile = xstrdup(value);
173 else if (!strcmp(name, "repo.group")) 173 else if (!strcmp(name, "repo.group"))
174 cgit_repo_group = xstrdup(value); 174 cgit_repo_group = xstrdup(value);
175 else if (!strcmp(name, "repo.url")) 175 else if (!strcmp(name, "repo.url"))
176 cgit_repo = add_repo(value); 176 cgit_repo = add_repo(value);
177 else if (!strcmp(name, "repo.name")) 177 else if (!strcmp(name, "repo.name"))
178 cgit_repo->name = xstrdup(value); 178 cgit_repo->name = xstrdup(value);
179 else if (cgit_repo && !strcmp(name, "repo.path")) 179 else if (cgit_repo && !strcmp(name, "repo.path"))
180 cgit_repo->path = xstrdup(value); 180 cgit_repo->path = xstrdup(value);
181 else if (cgit_repo && !strcmp(name, "repo.desc")) 181 else if (cgit_repo && !strcmp(name, "repo.desc"))
182 cgit_repo->desc = xstrdup(value); 182 cgit_repo->desc = xstrdup(value);
183 else if (cgit_repo && !strcmp(name, "repo.owner")) 183 else if (cgit_repo && !strcmp(name, "repo.owner"))
184 cgit_repo->owner = xstrdup(value); 184 cgit_repo->owner = xstrdup(value);
185 else if (cgit_repo && !strcmp(name, "repo.defbranch")) 185 else if (cgit_repo && !strcmp(name, "repo.defbranch"))
186 cgit_repo->defbranch = xstrdup(value); 186 cgit_repo->defbranch = xstrdup(value);
187 else if (cgit_repo && !strcmp(name, "repo.snapshots")) 187 else if (cgit_repo && !strcmp(name, "repo.snapshots"))
188 cgit_repo->snapshots = cgit_snapshots * atoi(value); 188 cgit_repo->snapshots = cgit_snapshots * atoi(value);
189 else if (cgit_repo && !strcmp(name, "repo.enable-log-filecount")) 189 else if (cgit_repo && !strcmp(name, "repo.enable-log-filecount"))
190 cgit_repo->enable_log_filecount = cgit_enable_log_filecount * atoi(value); 190 cgit_repo->enable_log_filecount = cgit_enable_log_filecount * atoi(value);
191 else if (cgit_repo && !strcmp(name, "repo.enable-log-linecount")) 191 else if (cgit_repo && !strcmp(name, "repo.enable-log-linecount"))
192 cgit_repo->enable_log_linecount = cgit_enable_log_linecount * atoi(value); 192 cgit_repo->enable_log_linecount = cgit_enable_log_linecount * atoi(value);
193 else if (cgit_repo && !strcmp(name, "repo.module-link")) 193 else if (cgit_repo && !strcmp(name, "repo.module-link"))
194 cgit_repo->module_link= xstrdup(value); 194 cgit_repo->module_link= xstrdup(value);
195 else if (cgit_repo && !strcmp(name, "repo.readme") && value != NULL) { 195 else if (cgit_repo && !strcmp(name, "repo.readme") && value != NULL) {
196 if (*value == '/') 196 if (*value == '/')
197 cgit_repo->readme = xstrdup(value); 197 cgit_repo->readme = xstrdup(value);
198 else 198 else
199 cgit_repo->readme = xstrdup(fmt("%s/%s", cgit_repo->path, value)); 199 cgit_repo->readme = xstrdup(fmt("%s/%s", cgit_repo->path, value));
200 } else if (!strcmp(name, "include")) 200 } else if (!strcmp(name, "include"))
201 cgit_read_config(value, cgit_global_config_cb); 201 cgit_read_config(value, cgit_global_config_cb);
202} 202}
203 203
204void cgit_querystring_cb(const char *name, const char *value) 204void cgit_querystring_cb(const char *name, const char *value)
205{ 205{
206 if (!strcmp(name,"r")) { 206 if (!strcmp(name,"r")) {
207 cgit_query_repo = xstrdup(value); 207 cgit_query_repo = xstrdup(value);
208 cgit_repo = cgit_get_repoinfo(value); 208 cgit_repo = cgit_get_repoinfo(value);
209 } else if (!strcmp(name, "p")) { 209 } else if (!strcmp(name, "p")) {
210 cgit_query_page = xstrdup(value); 210 cgit_query_page = xstrdup(value);
211 cgit_cmd = cgit_get_cmd_index(value); 211 cgit_cmd = cgit_get_cmd_index(value);
212 } else if (!strcmp(name, "url")) { 212 } else if (!strcmp(name, "url")) {
213 cgit_parse_url(value); 213 cgit_parse_url(value);
214 } else if (!strcmp(name, "q")) { 214 } else if (!strcmp(name, "q")) {
215 cgit_query_search = xstrdup(value); 215 cgit_query_search = xstrdup(value);
216 } else if (!strcmp(name, "h")) { 216 } else if (!strcmp(name, "h")) {
217 cgit_query_head = xstrdup(value); 217 cgit_query_head = xstrdup(value);
218 cgit_query_has_symref = 1; 218 cgit_query_has_symref = 1;
219 } else if (!strcmp(name, "id")) { 219 } else if (!strcmp(name, "id")) {
220 cgit_query_sha1 = xstrdup(value); 220 cgit_query_sha1 = xstrdup(value);
221 cgit_query_has_sha1 = 1; 221 cgit_query_has_sha1 = 1;
222 } else if (!strcmp(name, "id2")) { 222 } else if (!strcmp(name, "id2")) {
223 cgit_query_sha2 = xstrdup(value); 223 cgit_query_sha2 = xstrdup(value);
224 cgit_query_has_sha1 = 1; 224 cgit_query_has_sha1 = 1;
225 } else if (!strcmp(name, "ofs")) { 225 } else if (!strcmp(name, "ofs")) {
226 cgit_query_ofs = atoi(value); 226 cgit_query_ofs = atoi(value);
227 } else if (!strcmp(name, "path")) { 227 } else if (!strcmp(name, "path")) {
228 cgit_query_path = xstrdup(value); 228 cgit_query_path = xstrdup(value);
229 } else if (!strcmp(name, "name")) { 229 } else if (!strcmp(name, "name")) {
230 cgit_query_name = xstrdup(value); 230 cgit_query_name = xstrdup(value);
231 } 231 }
232} 232}
233 233
234void *cgit_free_commitinfo(struct commitinfo *info) 234void *cgit_free_commitinfo(struct commitinfo *info)
235{ 235{
236 free(info->author); 236 free(info->author);
237 free(info->author_email); 237 free(info->author_email);
238 free(info->committer); 238 free(info->committer);
239 free(info->committer_email); 239 free(info->committer_email);
240 free(info->subject); 240 free(info->subject);
241 free(info); 241 free(info);
242 return NULL; 242 return NULL;
243} 243}
244 244
245int hextoint(char c) 245int hextoint(char c)
246{ 246{
247 if (c >= 'a' && c <= 'f') 247 if (c >= 'a' && c <= 'f')
248 return 10 + c - 'a'; 248 return 10 + c - 'a';
249 else if (c >= 'A' && c <= 'F') 249 else if (c >= 'A' && c <= 'F')
250 return 10 + c - 'A'; 250 return 10 + c - 'A';
251 else if (c >= '0' && c <= '9') 251 else if (c >= '0' && c <= '9')
252 return c - '0'; 252 return c - '0';
253 else 253 else
254 return -1; 254 return -1;
255} 255}
256 256
257void cgit_diff_tree_cb(struct diff_queue_struct *q, 257void cgit_diff_tree_cb(struct diff_queue_struct *q,
258 struct diff_options *options, void *data) 258 struct diff_options *options, void *data)
259{ 259{
260 int i; 260 int i;
261 261
262 for (i = 0; i < q->nr; i++) { 262 for (i = 0; i < q->nr; i++) {
263 if (q->queue[i]->status == 'U') 263 if (q->queue[i]->status == 'U')
264 continue; 264 continue;
265 ((filepair_fn)data)(q->queue[i]); 265 ((filepair_fn)data)(q->queue[i]);
266 } 266 }
267} 267}
268 268
269static int load_mmfile(mmfile_t *file, const unsigned char *sha1) 269static int load_mmfile(mmfile_t *file, const unsigned char *sha1)
270{ 270{
271 enum object_type type; 271 enum object_type type;
272 272
273 if (is_null_sha1(sha1)) { 273 if (is_null_sha1(sha1)) {
274 file->ptr = (char *)""; 274 file->ptr = (char *)"";
275 file->size = 0; 275 file->size = 0;
276 } else { 276 } else {
277 file->ptr = read_sha1_file(sha1, &type, &file->size); 277 file->ptr = read_sha1_file(sha1, &type, &file->size);
278 } 278 }
279 return 1; 279 return 1;
280} 280}
281 281
282/* 282/*
283 * Receive diff-buffers from xdiff and concatenate them as 283 * Receive diff-buffers from xdiff and concatenate them as
284 * needed across multiple callbacks. 284 * needed across multiple callbacks.
285 * 285 *
286 * This is basically a copy of xdiff-interface.c/xdiff_outf(), 286 * This is basically a copy of xdiff-interface.c/xdiff_outf(),
287 * ripped from git and modified to use globals instead of 287 * ripped from git and modified to use globals instead of
288 * a special callback-struct. 288 * a special callback-struct.
289 */ 289 */
290char *diffbuf = NULL; 290char *diffbuf = NULL;
291int buflen = 0; 291int buflen = 0;
292 292
293int filediff_cb(void *priv, mmbuffer_t *mb, int nbuf) 293int filediff_cb(void *priv, mmbuffer_t *mb, int nbuf)
294{ 294{
295 int i; 295 int i;
296 296
297 for (i = 0; i < nbuf; i++) { 297 for (i = 0; i < nbuf; i++) {
298 if (mb[i].ptr[mb[i].size-1] != '\n') { 298 if (mb[i].ptr[mb[i].size-1] != '\n') {
299 /* Incomplete line */ 299 /* Incomplete line */
300 diffbuf = xrealloc(diffbuf, buflen + mb[i].size); 300 diffbuf = xrealloc(diffbuf, buflen + mb[i].size);
301 memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size); 301 memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size);
302 buflen += mb[i].size; 302 buflen += mb[i].size;
303 continue; 303 continue;
304 } 304 }
305 305
306 /* we have a complete line */ 306 /* we have a complete line */
307 if (!diffbuf) { 307 if (!diffbuf) {
308 ((linediff_fn)priv)(mb[i].ptr, mb[i].size); 308 ((linediff_fn)priv)(mb[i].ptr, mb[i].size);
309 continue; 309 continue;
310 } 310 }
311 diffbuf = xrealloc(diffbuf, buflen + mb[i].size); 311 diffbuf = xrealloc(diffbuf, buflen + mb[i].size);
312 memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size); 312 memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size);
313 ((linediff_fn)priv)(diffbuf, buflen + mb[i].size); 313 ((linediff_fn)priv)(diffbuf, buflen + mb[i].size);
314 free(diffbuf); 314 free(diffbuf);
315 diffbuf = NULL; 315 diffbuf = NULL;
316 buflen = 0; 316 buflen = 0;
317 } 317 }
318 if (diffbuf) { 318 if (diffbuf) {
319 ((linediff_fn)priv)(diffbuf, buflen); 319 ((linediff_fn)priv)(diffbuf, buflen);
320 free(diffbuf); 320 free(diffbuf);
321 diffbuf = NULL; 321 diffbuf = NULL;
322 buflen = 0; 322 buflen = 0;
323 } 323 }
324 return 0; 324 return 0;
325} 325}
326 326
327int cgit_diff_files(const unsigned char *old_sha1, 327int cgit_diff_files(const unsigned char *old_sha1,
328 const unsigned char *new_sha1, 328 const unsigned char *new_sha1,
329 linediff_fn fn) 329 linediff_fn fn)
330{ 330{
331 mmfile_t file1, file2; 331 mmfile_t file1, file2;
332 xpparam_t diff_params; 332 xpparam_t diff_params;
333 xdemitconf_t emit_params; 333 xdemitconf_t emit_params;
334 xdemitcb_t emit_cb; 334 xdemitcb_t emit_cb;
335 335
336 if (!load_mmfile(&file1, old_sha1) || !load_mmfile(&file2, new_sha1)) 336 if (!load_mmfile(&file1, old_sha1) || !load_mmfile(&file2, new_sha1))
337 return 1; 337 return 1;
338 338
339 diff_params.flags = XDF_NEED_MINIMAL; 339 diff_params.flags = XDF_NEED_MINIMAL;
340 emit_params.ctxlen = 3; 340 emit_params.ctxlen = 3;
341 emit_params.flags = XDL_EMIT_FUNCNAMES; 341 emit_params.flags = XDL_EMIT_FUNCNAMES;
342 emit_cb.outf = filediff_cb; 342 emit_cb.outf = filediff_cb;
343 emit_cb.priv = fn; 343 emit_cb.priv = fn;
344 xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb); 344 xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb);
345 return 0; 345 return 0;
346} 346}
347 347
348void cgit_diff_tree(const unsigned char *old_sha1, 348void cgit_diff_tree(const unsigned char *old_sha1,
349 const unsigned char *new_sha1, 349 const unsigned char *new_sha1,
350 filepair_fn fn) 350 filepair_fn fn)
351{ 351{
352 struct diff_options opt; 352 struct diff_options opt;
353 int ret; 353 int ret;
354 354
355 diff_setup(&opt); 355 diff_setup(&opt);
356 opt.output_format = DIFF_FORMAT_CALLBACK; 356 opt.output_format = DIFF_FORMAT_CALLBACK;
357 opt.detect_rename = 1; 357 opt.detect_rename = 1;
358 opt.recursive = 1; 358 opt.recursive = 1;
359 opt.format_callback = cgit_diff_tree_cb; 359 opt.format_callback = cgit_diff_tree_cb;
360 opt.format_callback_data = fn; 360 opt.format_callback_data = fn;
361 diff_setup_done(&opt); 361 diff_setup_done(&opt);
362 362
363 if (old_sha1) 363 if (old_sha1 && !is_null_sha1(old_sha1))
364 ret = diff_tree_sha1(old_sha1, new_sha1, "", &opt); 364 ret = diff_tree_sha1(old_sha1, new_sha1, "", &opt);
365 else 365 else
366 ret = diff_root_tree_sha1(new_sha1, "", &opt); 366 ret = diff_root_tree_sha1(new_sha1, "", &opt);
367 diffcore_std(&opt); 367 diffcore_std(&opt);
368 diff_flush(&opt); 368 diff_flush(&opt);
369} 369}
370 370
371void cgit_diff_commit(struct commit *commit, filepair_fn fn) 371void cgit_diff_commit(struct commit *commit, filepair_fn fn)
372{ 372{
373 unsigned char *old_sha1 = NULL; 373 unsigned char *old_sha1 = NULL;
374 374
375 if (commit->parents) 375 if (commit->parents)
376 old_sha1 = commit->parents->item->object.sha1; 376 old_sha1 = commit->parents->item->object.sha1;
377 cgit_diff_tree(old_sha1, commit->object.sha1, fn); 377 cgit_diff_tree(old_sha1, commit->object.sha1, fn);
378} 378}