summaryrefslogtreecommitdiffabout
path: root/shared.c
Unidiff
Diffstat (limited to 'shared.c') (more/less context) (ignore whitespace changes)
-rw-r--r--shared.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/shared.c b/shared.c
index cce0af4..288cfa2 100644
--- a/shared.c
+++ b/shared.c
@@ -230,128 +230,163 @@ int filediff_cb(void *priv, mmbuffer_t *mb, int nbuf)
230 if (mb[i].ptr[mb[i].size-1] != '\n') { 230 if (mb[i].ptr[mb[i].size-1] != '\n') {
231 /* Incomplete line */ 231 /* Incomplete line */
232 diffbuf = xrealloc(diffbuf, buflen + mb[i].size); 232 diffbuf = xrealloc(diffbuf, buflen + mb[i].size);
233 memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size); 233 memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size);
234 buflen += mb[i].size; 234 buflen += mb[i].size;
235 continue; 235 continue;
236 } 236 }
237 237
238 /* we have a complete line */ 238 /* we have a complete line */
239 if (!diffbuf) { 239 if (!diffbuf) {
240 ((linediff_fn)priv)(mb[i].ptr, mb[i].size); 240 ((linediff_fn)priv)(mb[i].ptr, mb[i].size);
241 continue; 241 continue;
242 } 242 }
243 diffbuf = xrealloc(diffbuf, buflen + mb[i].size); 243 diffbuf = xrealloc(diffbuf, buflen + mb[i].size);
244 memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size); 244 memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size);
245 ((linediff_fn)priv)(diffbuf, buflen + mb[i].size); 245 ((linediff_fn)priv)(diffbuf, buflen + mb[i].size);
246 free(diffbuf); 246 free(diffbuf);
247 diffbuf = NULL; 247 diffbuf = NULL;
248 buflen = 0; 248 buflen = 0;
249 } 249 }
250 if (diffbuf) { 250 if (diffbuf) {
251 ((linediff_fn)priv)(diffbuf, buflen); 251 ((linediff_fn)priv)(diffbuf, buflen);
252 free(diffbuf); 252 free(diffbuf);
253 diffbuf = NULL; 253 diffbuf = NULL;
254 buflen = 0; 254 buflen = 0;
255 } 255 }
256 return 0; 256 return 0;
257} 257}
258 258
259int cgit_diff_files(const unsigned char *old_sha1, 259int cgit_diff_files(const unsigned char *old_sha1,
260 const unsigned char *new_sha1, unsigned long *old_size, 260 const unsigned char *new_sha1, unsigned long *old_size,
261 unsigned long *new_size, int *binary, linediff_fn fn) 261 unsigned long *new_size, int *binary, linediff_fn fn)
262{ 262{
263 mmfile_t file1, file2; 263 mmfile_t file1, file2;
264 xpparam_t diff_params; 264 xpparam_t diff_params;
265 xdemitconf_t emit_params; 265 xdemitconf_t emit_params;
266 xdemitcb_t emit_cb; 266 xdemitcb_t emit_cb;
267 267
268 if (!load_mmfile(&file1, old_sha1) || !load_mmfile(&file2, new_sha1)) 268 if (!load_mmfile(&file1, old_sha1) || !load_mmfile(&file2, new_sha1))
269 return 1; 269 return 1;
270 270
271 *old_size = file1.size; 271 *old_size = file1.size;
272 *new_size = file2.size; 272 *new_size = file2.size;
273 273
274 if ((file1.ptr && buffer_is_binary(file1.ptr, file1.size)) || 274 if ((file1.ptr && buffer_is_binary(file1.ptr, file1.size)) ||
275 (file2.ptr && buffer_is_binary(file2.ptr, file2.size))) { 275 (file2.ptr && buffer_is_binary(file2.ptr, file2.size))) {
276 *binary = 1; 276 *binary = 1;
277 return 0; 277 return 0;
278 } 278 }
279 279
280 memset(&diff_params, 0, sizeof(diff_params)); 280 memset(&diff_params, 0, sizeof(diff_params));
281 memset(&emit_params, 0, sizeof(emit_params)); 281 memset(&emit_params, 0, sizeof(emit_params));
282 memset(&emit_cb, 0, sizeof(emit_cb)); 282 memset(&emit_cb, 0, sizeof(emit_cb));
283 diff_params.flags = XDF_NEED_MINIMAL; 283 diff_params.flags = XDF_NEED_MINIMAL;
284 emit_params.ctxlen = 3; 284 emit_params.ctxlen = 3;
285 emit_params.flags = XDL_EMIT_FUNCNAMES; 285 emit_params.flags = XDL_EMIT_FUNCNAMES;
286 emit_cb.outf = filediff_cb; 286 emit_cb.outf = filediff_cb;
287 emit_cb.priv = fn; 287 emit_cb.priv = fn;
288 xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb); 288 xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb);
289 return 0; 289 return 0;
290} 290}
291 291
292void cgit_diff_tree(const unsigned char *old_sha1, 292void cgit_diff_tree(const unsigned char *old_sha1,
293 const unsigned char *new_sha1, 293 const unsigned char *new_sha1,
294 filepair_fn fn, const char *prefix) 294 filepair_fn fn, const char *prefix)
295{ 295{
296 struct diff_options opt; 296 struct diff_options opt;
297 int ret; 297 int ret;
298 int prefixlen; 298 int prefixlen;
299 299
300 diff_setup(&opt); 300 diff_setup(&opt);
301 opt.output_format = DIFF_FORMAT_CALLBACK; 301 opt.output_format = DIFF_FORMAT_CALLBACK;
302 opt.detect_rename = 1; 302 opt.detect_rename = 1;
303 opt.rename_limit = ctx.cfg.renamelimit; 303 opt.rename_limit = ctx.cfg.renamelimit;
304 DIFF_OPT_SET(&opt, RECURSIVE); 304 DIFF_OPT_SET(&opt, RECURSIVE);
305 opt.format_callback = cgit_diff_tree_cb; 305 opt.format_callback = cgit_diff_tree_cb;
306 opt.format_callback_data = fn; 306 opt.format_callback_data = fn;
307 if (prefix) { 307 if (prefix) {
308 opt.nr_paths = 1; 308 opt.nr_paths = 1;
309 opt.paths = &prefix; 309 opt.paths = &prefix;
310 prefixlen = strlen(prefix); 310 prefixlen = strlen(prefix);
311 opt.pathlens = &prefixlen; 311 opt.pathlens = &prefixlen;
312 } 312 }
313 diff_setup_done(&opt); 313 diff_setup_done(&opt);
314 314
315 if (old_sha1 && !is_null_sha1(old_sha1)) 315 if (old_sha1 && !is_null_sha1(old_sha1))
316 ret = diff_tree_sha1(old_sha1, new_sha1, "", &opt); 316 ret = diff_tree_sha1(old_sha1, new_sha1, "", &opt);
317 else 317 else
318 ret = diff_root_tree_sha1(new_sha1, "", &opt); 318 ret = diff_root_tree_sha1(new_sha1, "", &opt);
319 diffcore_std(&opt); 319 diffcore_std(&opt);
320 diff_flush(&opt); 320 diff_flush(&opt);
321} 321}
322 322
323void cgit_diff_commit(struct commit *commit, filepair_fn fn) 323void cgit_diff_commit(struct commit *commit, filepair_fn fn)
324{ 324{
325 unsigned char *old_sha1 = NULL; 325 unsigned char *old_sha1 = NULL;
326 326
327 if (commit->parents) 327 if (commit->parents)
328 old_sha1 = commit->parents->item->object.sha1; 328 old_sha1 = commit->parents->item->object.sha1;
329 cgit_diff_tree(old_sha1, commit->object.sha1, fn, NULL); 329 cgit_diff_tree(old_sha1, commit->object.sha1, fn, NULL);
330} 330}
331 331
332int cgit_parse_snapshots_mask(const char *str) 332int cgit_parse_snapshots_mask(const char *str)
333{ 333{
334 const struct cgit_snapshot_format *f; 334 const struct cgit_snapshot_format *f;
335 static const char *delim = " \t,:/|;"; 335 static const char *delim = " \t,:/|;";
336 int tl, sl, rv = 0; 336 int tl, sl, rv = 0;
337 337
338 /* favor legacy setting */ 338 /* favor legacy setting */
339 if(atoi(str)) 339 if(atoi(str))
340 return 1; 340 return 1;
341 for(;;) { 341 for(;;) {
342 str += strspn(str,delim); 342 str += strspn(str,delim);
343 tl = strcspn(str,delim); 343 tl = strcspn(str,delim);
344 if (!tl) 344 if (!tl)
345 break; 345 break;
346 for (f = cgit_snapshot_formats; f->suffix; f++) { 346 for (f = cgit_snapshot_formats; f->suffix; f++) {
347 sl = strlen(f->suffix); 347 sl = strlen(f->suffix);
348 if((tl == sl && !strncmp(f->suffix, str, tl)) || 348 if((tl == sl && !strncmp(f->suffix, str, tl)) ||
349 (tl == sl-1 && !strncmp(f->suffix+1, str, tl-1))) { 349 (tl == sl-1 && !strncmp(f->suffix+1, str, tl-1))) {
350 rv |= f->bit; 350 rv |= f->bit;
351 break; 351 break;
352 } 352 }
353 } 353 }
354 str += tl; 354 str += tl;
355 } 355 }
356 return rv; 356 return rv;
357} 357}
358
359int cgit_open_filter(struct cgit_filter *filter)
360{
361
362 filter->old_stdout = chk_positive(dup(STDOUT_FILENO),
363 "Unable to duplicate STDOUT");
364 chk_zero(pipe(filter->pipe_fh), "Unable to create pipe to subprocess");
365 filter->pid = chk_non_negative(fork(), "Unable to create subprocess");
366 if (filter->pid == 0) {
367 close(filter->pipe_fh[1]);
368 chk_non_negative(dup2(filter->pipe_fh[0], STDIN_FILENO),
369 "Unable to use pipe as STDIN");
370 execvp(filter->cmd, filter->argv);
371 die("Unable to exec subprocess %s: %s (%d)", filter->cmd,
372 strerror(errno), errno);
373 }
374 close(filter->pipe_fh[0]);
375 chk_non_negative(dup2(filter->pipe_fh[1], STDOUT_FILENO),
376 "Unable to use pipe as STDOUT");
377 close(filter->pipe_fh[1]);
378 return 0;
379}
380
381int cgit_close_filter(struct cgit_filter *filter)
382{
383 chk_non_negative(dup2(filter->old_stdout, STDOUT_FILENO),
384 "Unable to restore STDOUT");
385 close(filter->old_stdout);
386 if (filter->pid < 0)
387 return 0;
388 waitpid(filter->pid, &filter->exitstatus, 0);
389 if (WIFEXITED(filter->exitstatus) && !WEXITSTATUS(filter->exitstatus))
390 return 0;
391 die("Subprocess %s exited abnormally", filter->cmd);
392}