Annotation of src/usr.bin/cvs/diff.c, Revision 1.145
1.145 ! joris 1: /* $OpenBSD: diff.c,v 1.144 2008/06/20 14:04:29 tobias Exp $ */
1.1 jfb 2: /*
1.136 tobias 3: * Copyright (c) 2008 Tobias Stoeckmann <tobias@openbsd.org>
1.91 joris 4: * Copyright (c) 2006 Joris Vink <joris@openbsd.org>
1.1 jfb 5: *
1.91 joris 6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1.1 jfb 17: */
18:
1.118 otto 19: #include <sys/stat.h>
1.125 tobias 20: #include <sys/time.h>
1.118 otto 21:
22: #include <errno.h>
1.131 joris 23: #include <fcntl.h>
1.125 tobias 24: #include <stdlib.h>
1.118 otto 25: #include <string.h>
1.139 tobias 26: #include <time.h>
1.118 otto 27: #include <unistd.h>
1.1 jfb 28:
29: #include "cvs.h"
1.56 niallo 30: #include "diff.h"
1.108 joris 31: #include "remote.h"
1.86 joris 32:
1.91 joris 33: void cvs_diff_local(struct cvs_file *);
1.46 xsa 34:
1.126 tobias 35: static int Nflag = 0;
36: static int force_head = 0;
37: static char *koptstr;
38: static char *rev1 = NULL;
39: static char *rev2 = NULL;
1.137 tobias 40: static time_t date1 = -1;
41: static time_t date2 = -1;
1.144 tobias 42: static char *dateflag1 = NULL;
43: static char *dateflag2 = NULL;
1.94 joris 44:
1.36 jfb 45: struct cvs_cmd cvs_cmd_diff = {
1.124 tobias 46: CVS_OP_DIFF, CVS_USE_WDIR, "diff",
1.36 jfb 47: { "di", "dif" },
48: "Show differences between revisions",
1.122 tobias 49: "[-cilNnpRu] [[-D date] [-r rev] [-D date2 | -r rev2]] "
1.43 xsa 50: "[-k mode] [file ...]",
1.126 tobias 51: "cfD:ik:lNnpr:Ru",
1.125 tobias 52: NULL,
53: cvs_diff
54: };
55:
56: struct cvs_cmd cvs_cmd_rdiff = {
57: CVS_OP_RDIFF, 0, "rdiff",
58: { "patch", "pa" },
59: "Show differences between revisions",
60: "[-flR] [-c | -u] [-s | -t] [-V ver] -D date | -r rev\n"
61: "[-D date2 | -r rev2] [-k mode] module ...",
1.126 tobias 62: "cfD:k:lr:RuV:",
1.36 jfb 63: NULL,
1.91 joris 64: cvs_diff
1.36 jfb 65: };
66:
1.91 joris 67: int
68: cvs_diff(int argc, char **argv)
1.1 jfb 69: {
1.127 tobias 70: int ch, flags;
1.91 joris 71: char *arg = ".";
72: struct cvs_recursion cr;
1.1 jfb 73:
1.92 joris 74: flags = CR_RECURSE_DIRS;
1.128 tobias 75: strlcpy(diffargs, cvs_cmdop == CVS_OP_DIFF ? "diff" : "rdiff",
76: sizeof(diffargs));
1.1 jfb 77:
1.127 tobias 78: while ((ch = getopt(argc, argv, cvs_cmdop == CVS_OP_DIFF ?
79: cvs_cmd_diff.cmd_opts : cvs_cmd_rdiff.cmd_opts)) != -1) {
1.1 jfb 80: switch (ch) {
81: case 'c':
1.2 jfb 82: strlcat(diffargs, " -c", sizeof(diffargs));
1.58 niallo 83: diff_format = D_CONTEXT;
1.1 jfb 84: break;
1.137 tobias 85: case 'D':
86: if (date1 == -1 && rev1 == NULL) {
87: date1 = cvs_date_parse(optarg);
1.144 tobias 88: dateflag1 = optarg;
1.137 tobias 89: } else if (date2 == -1 && rev2 == NULL) {
90: date2 = cvs_date_parse(optarg);
1.144 tobias 91: dateflag2 = optarg;
1.137 tobias 92: } else {
93: fatal("no more than 2 revisions/dates can"
94: " be specified");
95: }
96: break;
1.125 tobias 97: case 'f':
98: force_head = 1;
99: break;
100: case 'i':
101: strlcat(diffargs, " -i", sizeof(diffargs));
102: diff_iflag = 1;
103: break;
1.126 tobias 104: case 'k':
105: koptstr = optarg;
106: kflag = rcs_kflag_get(koptstr);
1.132 deraadt 107: if (RCS_KWEXP_INVAL(kflag)) {
1.126 tobias 108: cvs_log(LP_ERR,
1.135 tobias 109: "invalid RCS keyword expansion mode");
1.133 tobias 110: fatal("%s", cvs_cmdop == CVS_OP_DIFF ?
111: cvs_cmd_diff.cmd_synopsis :
112: cvs_cmd_rdiff.cmd_synopsis);
1.126 tobias 113: }
114: break;
1.92 joris 115: case 'l':
116: flags &= ~CR_RECURSE_DIRS;
117: break;
1.33 jfb 118: case 'n':
119: strlcat(diffargs, " -n", sizeof(diffargs));
1.58 niallo 120: diff_format = D_RCSDIFF;
1.33 jfb 121: break;
1.94 joris 122: case 'N':
1.136 tobias 123: strlcat(diffargs, " -N", sizeof(diffargs));
1.95 joris 124: Nflag = 1;
1.94 joris 125: break;
1.101 joris 126: case 'p':
127: strlcat(diffargs, " -p", sizeof(diffargs));
128: diff_pflag = 1;
1.122 tobias 129: break;
130: case 'R':
131: flags |= CR_RECURSE_DIRS;
1.101 joris 132: break;
1.1 jfb 133: case 'r':
1.137 tobias 134: if (date1 == -1 && rev1 == NULL) {
1.97 joris 135: rev1 = optarg;
1.137 tobias 136: } else if (date2 == -1 && rev2 == NULL) {
1.97 joris 137: rev2 = optarg;
1.23 joris 138: } else {
1.91 joris 139: fatal("no more than 2 revisions/dates can"
140: " be specified");
1.1 jfb 141: }
1.32 joris 142: break;
1.1 jfb 143: case 'u':
1.2 jfb 144: strlcat(diffargs, " -u", sizeof(diffargs));
1.58 niallo 145: diff_format = D_UNIFIED;
1.1 jfb 146: break;
1.126 tobias 147: case 'V':
148: fatal("the -V option is obsolete "
149: "and should not be used");
1.1 jfb 150: default:
1.133 tobias 151: fatal("%s", cvs_cmdop == CVS_OP_DIFF ?
152: cvs_cmd_diff.cmd_synopsis :
153: cvs_cmd_rdiff.cmd_synopsis);
1.36 jfb 154: }
1.13 jfb 155: }
156:
1.91 joris 157: argc -= optind;
158: argv += optind;
1.1 jfb 159:
1.91 joris 160: cr.enterdir = NULL;
161: cr.leavedir = NULL;
1.108 joris 162:
1.125 tobias 163: if (cvs_cmdop == CVS_OP_RDIFF) {
1.144 tobias 164: if (rev1 == NULL && rev2 == NULL && dateflag1 == NULL &&
165: dateflag2 == NULL)
1.125 tobias 166: fatal("must specify at least one revision/date!");
167:
1.136 tobias 168: if (!argc)
169: fatal("%s", cvs_cmd_rdiff.cmd_synopsis);
170:
1.125 tobias 171: if (!diff_format) {
172: strlcat(diffargs, " -c", sizeof(diffargs));
173: diff_format = D_CONTEXT;
174: }
175:
176: flags |= CR_REPO;
177: }
178:
1.108 joris 179: if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
1.110 joris 180: cvs_client_connect_to_server();
1.108 joris 181: cr.fileproc = cvs_client_sendfile;
182:
183: if (!(flags & CR_RECURSE_DIRS))
184: cvs_client_send_request("Argument -l");
185:
1.126 tobias 186: if (kflag)
187: cvs_client_send_request("Argument -k%s", koptstr);
188:
1.108 joris 189: switch (diff_format) {
190: case D_CONTEXT:
191: cvs_client_send_request("Argument -c");
192: break;
193: case D_RCSDIFF:
194: cvs_client_send_request("Argument -n");
195: break;
196: case D_UNIFIED:
197: cvs_client_send_request("Argument -u");
198: break;
199: default:
200: break;
201: }
202:
203: if (Nflag == 1)
204: cvs_client_send_request("Argument -N");
205:
206: if (diff_pflag == 1)
207: cvs_client_send_request("Argument -p");
208:
209: if (rev1 != NULL)
210: cvs_client_send_request("Argument -r%s", rev1);
211: if (rev2 != NULL)
212: cvs_client_send_request("Argument -r%s", rev2);
1.144 tobias 213:
214: if (dateflag1 != NULL)
215: cvs_client_send_request("Argument -D%s", dateflag1);
216: if (dateflag2 != NULL)
217: cvs_client_send_request("Argument -D%s", dateflag2);
1.108 joris 218: } else {
1.125 tobias 219: if (cvs_cmdop == CVS_OP_RDIFF &&
220: chdir(current_cvsroot->cr_dir) == -1)
221: fatal("cvs_diff: %s", strerror(errno));
222:
1.108 joris 223: cr.fileproc = cvs_diff_local;
224: }
225:
1.92 joris 226: cr.flags = flags;
1.7 jfb 227:
1.97 joris 228: diff_rev1 = diff_rev2 = NULL;
229:
1.125 tobias 230: if (cvs_cmdop == CVS_OP_DIFF ||
231: current_cvsroot->cr_method == CVS_METHOD_LOCAL) {
232: if (argc > 0)
233: cvs_file_run(argc, argv, &cr);
234: else
235: cvs_file_run(1, &arg, &cr);
236: }
1.108 joris 237:
238: if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
239: cvs_client_send_files(argv, argc);
240: cvs_client_senddir(".");
1.125 tobias 241:
242: cvs_client_send_request((cvs_cmdop == CVS_OP_RDIFF) ?
243: "rdiff" : "diff");
244:
1.108 joris 245: cvs_client_get_responses();
246: }
1.36 jfb 247:
248: return (0);
249: }
250:
1.91 joris 251: void
252: cvs_diff_local(struct cvs_file *cf)
1.36 jfb 253: {
1.114 joris 254: BUF *b1;
1.131 joris 255: int fd1, fd2;
1.91 joris 256: struct stat st;
1.69 niallo 257: struct timeval tv[2], tv2[2];
1.139 tobias 258: struct tm datetm;
1.137 tobias 259: char rbuf[CVS_REV_BUFSZ], tbuf[CVS_TIME_BUFSZ], *p1, *p2;
1.111 xsa 260:
1.114 joris 261: b1 = NULL;
1.136 tobias 262: fd1 = fd2 = -1;
263: p1 = p2 = NULL;
1.69 niallo 264:
1.91 joris 265: cvs_log(LP_TRACE, "cvs_diff_local(%s)", cf->file_path);
1.1 jfb 266:
1.91 joris 267: if (cf->file_type == CVS_DIR) {
1.46 xsa 268: if (verbosity > 1)
1.91 joris 269: cvs_log(LP_NOTICE, "Diffing inside %s", cf->file_path);
1.1 jfb 270: return;
271: }
272:
1.121 joris 273: cvs_file_classify(cf, cvs_directory_tag);
1.1 jfb 274:
1.136 tobias 275: if (cvs_cmdop == CVS_OP_DIFF) {
276: if (cf->file_ent == NULL) {
277: cvs_log(LP_ERR, "I know nothing about %s",
278: cf->file_path);
279: return;
280: }
1.126 tobias 281:
1.136 tobias 282: switch (cf->file_ent->ce_status) {
283: case CVS_ENT_ADDED:
284: if (Nflag == 0) {
285: cvs_log(LP_ERR, "%s is a new entry, no "
286: "comparison available", cf->file_path);
1.125 tobias 287: return;
288: }
1.145 ! joris 289: if (!(cf->file_flags & FILE_ON_DISK)) {
! 290: cvs_log(LP_ERR, "cannot find %s",
! 291: cf->file_path);
1.136 tobias 292: return;
1.125 tobias 293: }
1.136 tobias 294: break;
295: case CVS_ENT_REMOVED:
296: if (Nflag == 0) {
297: cvs_log(LP_ERR, "%s was removed, no "
298: "comparison available", cf->file_path);
1.125 tobias 299: return;
300: }
1.136 tobias 301: if (cf->file_rcs == NULL) {
302: cvs_log(LP_ERR, "cannot find RCS file for %s",
303: cf->file_path);
304: return;
1.125 tobias 305: }
1.136 tobias 306: break;
307: default:
1.145 ! joris 308: if (!(cf->file_flags & FILE_ON_DISK)) {
1.140 joris 309: cvs_log(LP_ERR, "cannot find %s",
1.138 tobias 310: cf->file_path);
1.136 tobias 311: return;
312: }
1.140 joris 313:
1.136 tobias 314: if (cf->file_rcs == NULL) {
315: cvs_log(LP_ERR, "cannot find RCS file for %s",
316: cf->file_path);
317: return;
318: }
319: break;
1.123 tobias 320: }
1.136 tobias 321: }
1.1 jfb 322:
1.137 tobias 323: if (cf->file_status == FILE_UPTODATE && rev1 == NULL && rev2 == NULL &&
324: date1 == -1 && date2 == -1)
1.125 tobias 325: return;
1.141 tobias 326:
1.142 joris 327: if (cf->file_rcs != NULL && cf->file_rcs->rf_head == NULL) {
1.141 tobias 328: cvs_log(LP_ERR, "no head revision in RCS file for %s\n",
329: cf->file_path);
330: return;
331: }
1.125 tobias 332:
1.136 tobias 333: if (kflag && cf->file_rcs != NULL)
334: rcs_kwexp_set(cf->file_rcs, kflag);
1.125 tobias 335:
1.136 tobias 336: if (cf->file_rcs == NULL)
337: diff_rev1 = NULL;
1.137 tobias 338: else if (rev1 != NULL || date1 != -1) {
339: cvs_specified_date = date1;
1.136 tobias 340: diff_rev1 = rcs_translate_tag(rev1, cf->file_rcs);
341: if (diff_rev1 == NULL && cvs_cmdop == CVS_OP_DIFF) {
1.143 tobias 342: if (rev1 != NULL) {
1.137 tobias 343: cvs_log(LP_ERR, "tag %s not in file %s", rev1,
344: cf->file_path);
1.143 tobias 345: goto cleanup;
346: } else if (Nflag) {
347: diff_rev1 = NULL;
348: } else {
1.139 tobias 349: gmtime_r(&cvs_specified_date, &datetm);
1.137 tobias 350: strftime(tbuf, sizeof(tbuf),
1.139 tobias 351: "%Y.%m.%d.%H.%M.%S", &datetm);
1.137 tobias 352: cvs_log(LP_ERR, "no revision for date %s in "
353: "file %s", tbuf, cf->file_path);
1.143 tobias 354: goto cleanup;
1.137 tobias 355: }
1.136 tobias 356: } else if (diff_rev1 == NULL && cvs_cmdop == CVS_OP_RDIFF &&
357: force_head) {
358: /* -f is not allowed for unknown symbols */
359: if ((diff_rev1 = rcsnum_parse(rev1)) == NULL)
360: fatal("no such tag %s", rev1);
361: rcsnum_free(diff_rev1);
1.1 jfb 362:
1.136 tobias 363: diff_rev1 = cf->file_rcs->rf_head;
364: }
1.137 tobias 365: cvs_specified_date = -1;
1.136 tobias 366: } else if (cvs_cmdop == CVS_OP_DIFF) {
367: if (cf->file_ent->ce_status == CVS_ENT_ADDED)
368: diff_rev1 = NULL;
1.94 joris 369: else
1.136 tobias 370: diff_rev1 = cf->file_ent->ce_rev;
371: }
1.1 jfb 372:
1.136 tobias 373: if (cf->file_rcs == NULL)
374: diff_rev2 = NULL;
1.137 tobias 375: else if (rev2 != NULL || date2 != -1) {
376: cvs_specified_date = date2;
1.136 tobias 377: diff_rev2 = rcs_translate_tag(rev2, cf->file_rcs);
378: if (diff_rev2 == NULL && cvs_cmdop == CVS_OP_DIFF) {
1.137 tobias 379: if (rev2 != NULL) {
380: cvs_log(LP_ERR, "tag %s not in file %s", rev2,
381: cf->file_path);
1.143 tobias 382: goto cleanup;
383: } else if (Nflag) {
384: diff_rev2 = NULL;
1.137 tobias 385: } else {
1.139 tobias 386: gmtime_r(&cvs_specified_date, &datetm);
1.137 tobias 387: strftime(tbuf, sizeof(tbuf),
1.139 tobias 388: "%Y.%m.%d.%H.%M.%S", &datetm);
1.137 tobias 389: cvs_log(LP_ERR, "no revision for date %s in "
390: "file %s", tbuf, cf->file_path);
1.143 tobias 391: goto cleanup;
1.137 tobias 392: }
1.136 tobias 393: } else if (diff_rev2 == NULL && cvs_cmdop == CVS_OP_RDIFF &&
394: force_head) {
395: /* -f is not allowed for unknown symbols */
396: if ((diff_rev2 = rcsnum_parse(rev2)) == NULL)
397: fatal("no such tag %s", rev2);
398: rcsnum_free(diff_rev2);
1.91 joris 399:
1.136 tobias 400: diff_rev2 = cf->file_rcs->rf_head;
401: }
1.137 tobias 402: cvs_specified_date = -1;
1.136 tobias 403: } else if (cvs_cmdop == CVS_OP_RDIFF)
404: diff_rev2 = cf->file_rcs->rf_head;
405: else if (cf->file_ent->ce_status == CVS_ENT_REMOVED)
406: diff_rev2 = NULL;
1.114 joris 407:
1.136 tobias 408: if (diff_rev1 != NULL && diff_rev2 != NULL &&
409: rcsnum_cmp(diff_rev1, diff_rev2, 0) == 0)
410: goto cleanup;
1.125 tobias 411:
1.136 tobias 412: switch (cvs_cmdop) {
413: case CVS_OP_DIFF:
1.143 tobias 414: if (cf->file_status == FILE_UPTODATE && diff_rev1 != NULL &&
1.136 tobias 415: rcsnum_cmp(diff_rev1, cf->file_rcsrev, 0) == 0)
416: goto cleanup;
417: break;
418: case CVS_OP_RDIFF:
419: if (diff_rev1 == NULL && diff_rev2 == NULL)
420: goto cleanup;
421: break;
422: }
423:
424: cvs_printf("Index: %s\n", cf->file_path);
425: if (cvs_cmdop == CVS_OP_DIFF)
426: cvs_printf("%s\nRCS file: %s\n", RCS_DIFF_DIV,
427: cf->file_rcs != NULL ? cf->file_rpath : cf->file_path);
428:
429: if (diff_rev1 != NULL) {
430: if (cvs_cmdop == CVS_OP_DIFF && diff_rev1 != NULL) {
431: (void)rcsnum_tostr(diff_rev1, rbuf, sizeof(rbuf));
432: cvs_printf("retrieving revision %s\n", rbuf);
1.125 tobias 433: }
1.136 tobias 434:
435: tv[0].tv_sec = rcs_rev_getdate(cf->file_rcs, diff_rev1);
436: tv[0].tv_usec = 0;
437: tv[1] = tv[0];
438:
439: (void)xasprintf(&p1, "%s/diff1.XXXXXXXXXX", cvs_tmpdir);
440: fd1 = rcs_rev_write_stmp(cf->file_rcs, diff_rev1, p1, 0);
441: if (futimes(fd1, tv) == -1)
442: fatal("cvs_diff_local: utimes failed");
1.94 joris 443: }
1.91 joris 444:
1.136 tobias 445: if (diff_rev2 != NULL) {
446: if (cvs_cmdop == CVS_OP_DIFF && rev2 != NULL) {
447: (void)rcsnum_tostr(diff_rev2, rbuf, sizeof(rbuf));
448: cvs_printf("retrieving revision %s\n", rbuf);
449: }
1.91 joris 450:
451: tv2[0].tv_sec = rcs_rev_getdate(cf->file_rcs, diff_rev2);
452: tv2[0].tv_usec = 0;
453: tv2[1] = tv2[0];
1.114 joris 454:
1.136 tobias 455: (void)xasprintf(&p2, "%s/diff2.XXXXXXXXXX", cvs_tmpdir);
1.131 joris 456: fd2 = rcs_rev_write_stmp(cf->file_rcs, diff_rev2, p2, 0);
457: if (futimes(fd2, tv2) == -1)
1.125 tobias 458: fatal("cvs_diff_local: utimes failed");
1.145 ! joris 459: } else if (cvs_cmdop == CVS_OP_DIFF &&
! 460: (cf->file_flags & FILE_ON_DISK) &&
1.136 tobias 461: cf->file_ent->ce_status != CVS_ENT_REMOVED) {
462: if (fstat(cf->fd, &st) == -1)
463: fatal("fstat failed %s", strerror(errno));
464: b1 = cvs_buf_load_fd(cf->fd);
1.125 tobias 465:
1.136 tobias 466: tv2[0].tv_sec = st.st_mtime;
467: tv2[0].tv_usec = 0;
468: tv2[1] = tv2[0];
1.121 joris 469:
1.136 tobias 470: (void)xasprintf(&p2, "%s/diff2.XXXXXXXXXX", cvs_tmpdir);
471: fd2 = cvs_buf_write_stmp(b1, p2, tv2);
472: cvs_buf_free(b1);
1.17 jfb 473: }
474:
1.136 tobias 475: switch (cvs_cmdop) {
476: case CVS_OP_DIFF:
1.125 tobias 477: cvs_printf("%s", diffargs);
478:
1.136 tobias 479: if (rev1 != NULL && diff_rev1 != NULL) {
480: (void)rcsnum_tostr(diff_rev1, rbuf, sizeof(rbuf));
1.125 tobias 481: cvs_printf(" -r%s", rbuf);
482:
1.136 tobias 483: if (rev2 != NULL && diff_rev2 != NULL) {
1.125 tobias 484: (void)rcsnum_tostr(diff_rev2, rbuf,
485: sizeof(rbuf));
486: cvs_printf(" -r%s", rbuf);
487: }
488: }
1.1 jfb 489:
1.125 tobias 490: if (diff_rev2 == NULL)
1.136 tobias 491: cvs_printf(" %s", cf->file_path);
1.130 tobias 492: cvs_printf("\n");
1.136 tobias 493: break;
494: case CVS_OP_RDIFF:
1.125 tobias 495: cvs_printf("diff ");
496: switch (diff_format) {
497: case D_CONTEXT:
498: cvs_printf("-c ");
499: break;
500: case D_RCSDIFF:
501: cvs_printf("-n ");
502: break;
503: case D_UNIFIED:
504: cvs_printf("-u ");
505: break;
506: default:
507: break;
508: }
509: if (diff_rev1 == NULL) {
510: cvs_printf("%s ", CVS_PATH_DEVNULL);
511: } else {
512: (void)rcsnum_tostr(diff_rev1, rbuf, sizeof(rbuf));
513: cvs_printf("%s:%s ", cf->file_path, rbuf);
514: }
1.1 jfb 515:
1.125 tobias 516: if (diff_rev2 == NULL) {
517: cvs_printf("%s:removed\n", cf->file_path);
518: } else {
519: (void)rcsnum_tostr(diff_rev2 != NULL ? diff_rev2 :
520: cf->file_rcs->rf_head, rbuf, sizeof(rbuf));
521: cvs_printf("%s:%s\n", cf->file_path, rbuf);
1.94 joris 522: }
1.136 tobias 523: break;
1.1 jfb 524: }
525:
1.136 tobias 526: if (fd1 == -1) {
527: if ((fd1 = open(CVS_PATH_DEVNULL, O_RDONLY, 0)) == -1)
528: fatal("cannot open %s", CVS_PATH_DEVNULL);
1.114 joris 529: }
1.136 tobias 530: if (fd2 == -1) {
531: if ((fd2 = open(CVS_PATH_DEVNULL, O_RDONLY, 0)) == -1)
532: fatal("cannot open %s", CVS_PATH_DEVNULL);
533: }
1.111 xsa 534:
1.136 tobias 535: if (cvs_diffreg(p1 != NULL ? cf->file_path : CVS_PATH_DEVNULL,
536: p2 != NULL ? cf->file_path : CVS_PATH_DEVNULL, fd1, fd2, NULL)
537: == D_ERROR)
1.111 xsa 538: fatal("cvs_diff_local: failed to get RCS patch");
1.131 joris 539:
540: close(fd1);
541: close(fd2);
1.58 niallo 542:
1.91 joris 543: cvs_worklist_run(&temp_files, cvs_worklist_unlink);
1.111 xsa 544:
545: if (p1 != NULL)
546: xfree(p1);
547: if (p2 != NULL)
548: xfree(p2);
1.101 joris 549:
1.136 tobias 550: cleanup:
551: if (diff_rev1 != NULL &&
552: (cf->file_rcs == NULL || diff_rev1 != cf->file_rcs->rf_head) &&
553: (cf->file_ent == NULL || diff_rev1 != cf->file_ent->ce_rev))
554: xfree(diff_rev1);
555: diff_rev1 = NULL;
1.94 joris 556:
1.136 tobias 557: if (diff_rev2 != NULL &&
558: (cf->file_rcs == NULL || diff_rev2 != cf->file_rcs->rf_head))
559: xfree(diff_rev2);
560: diff_rev2 = NULL;
1.1 jfb 561: }