author | Lars Hjemli <hjemli@gmail.com> | 2007-06-17 16:12:03 (UTC) |
---|---|---|
committer | Lars Hjemli <hjemli@gmail.com> | 2007-06-17 16:12:03 (UTC) |
commit | 4a0be586662843382ecfa53af34a13b291312bc0 (patch) (unidiff) | |
tree | 01e0cd725fe249df3449bb089aad9f8d58081f89 /shared.c | |
parent | faaca447b071592c9a1e1f14b4d0d2a39b4c795a (diff) | |
download | cgit-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>
-rw-r--r-- | shared.c | 2 |
1 files changed, 1 insertions, 1 deletions
@@ -171,208 +171,208 @@ void cgit_global_config_cb(const char *name, const char *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 | ||
204 | void cgit_querystring_cb(const char *name, const char *value) | 204 | void 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 | ||
234 | void *cgit_free_commitinfo(struct commitinfo *info) | 234 | void *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 | ||
245 | int hextoint(char c) | 245 | int 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 | ||
257 | void cgit_diff_tree_cb(struct diff_queue_struct *q, | 257 | void 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 | ||
269 | static int load_mmfile(mmfile_t *file, const unsigned char *sha1) | 269 | static 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 | */ |
290 | char *diffbuf = NULL; | 290 | char *diffbuf = NULL; |
291 | int buflen = 0; | 291 | int buflen = 0; |
292 | 292 | ||
293 | int filediff_cb(void *priv, mmbuffer_t *mb, int nbuf) | 293 | int 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 | ||
327 | int cgit_diff_files(const unsigned char *old_sha1, | 327 | int 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 | ||
348 | void cgit_diff_tree(const unsigned char *old_sha1, | 348 | void 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 | ||
371 | void cgit_diff_commit(struct commit *commit, filepair_fn fn) | 371 | void 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 | } |