Annotation of src/usr.bin/cvs/diff.c, Revision 1.148
1.148 ! joris 1: /* $OpenBSD: diff.c,v 1.147 2009/03/23 07:28:05 joris 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.147 joris 269: cvs_log(LP_ERR, "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.147 joris 309: cvs_printf("? %s\n", cf->file_path);
1.136 tobias 310: return;
311: }
1.140 joris 312:
1.136 tobias 313: if (cf->file_rcs == NULL) {
314: cvs_log(LP_ERR, "cannot find RCS file for %s",
315: cf->file_path);
316: return;
317: }
318: break;
1.123 tobias 319: }
1.136 tobias 320: }
1.1 jfb 321:
1.137 tobias 322: if (cf->file_status == FILE_UPTODATE && rev1 == NULL && rev2 == NULL &&
323: date1 == -1 && date2 == -1)
1.146 joris 324: return;
325:
326: if (cf->file_status == FILE_PATCH)
1.125 tobias 327: return;
1.141 tobias 328:
1.142 joris 329: if (cf->file_rcs != NULL && cf->file_rcs->rf_head == NULL) {
1.141 tobias 330: cvs_log(LP_ERR, "no head revision in RCS file for %s\n",
331: cf->file_path);
332: return;
333: }
1.125 tobias 334:
1.136 tobias 335: if (kflag && cf->file_rcs != NULL)
336: rcs_kwexp_set(cf->file_rcs, kflag);
1.125 tobias 337:
1.136 tobias 338: if (cf->file_rcs == NULL)
339: diff_rev1 = NULL;
1.137 tobias 340: else if (rev1 != NULL || date1 != -1) {
341: cvs_specified_date = date1;
1.136 tobias 342: diff_rev1 = rcs_translate_tag(rev1, cf->file_rcs);
343: if (diff_rev1 == NULL && cvs_cmdop == CVS_OP_DIFF) {
1.143 tobias 344: if (rev1 != NULL) {
1.137 tobias 345: cvs_log(LP_ERR, "tag %s not in file %s", rev1,
346: cf->file_path);
1.143 tobias 347: goto cleanup;
348: } else if (Nflag) {
349: diff_rev1 = NULL;
350: } else {
1.139 tobias 351: gmtime_r(&cvs_specified_date, &datetm);
1.137 tobias 352: strftime(tbuf, sizeof(tbuf),
1.139 tobias 353: "%Y.%m.%d.%H.%M.%S", &datetm);
1.137 tobias 354: cvs_log(LP_ERR, "no revision for date %s in "
355: "file %s", tbuf, cf->file_path);
1.143 tobias 356: goto cleanup;
1.137 tobias 357: }
1.136 tobias 358: } else if (diff_rev1 == NULL && cvs_cmdop == CVS_OP_RDIFF &&
359: force_head) {
360: /* -f is not allowed for unknown symbols */
361: if ((diff_rev1 = rcsnum_parse(rev1)) == NULL)
362: fatal("no such tag %s", rev1);
363: rcsnum_free(diff_rev1);
1.1 jfb 364:
1.136 tobias 365: diff_rev1 = cf->file_rcs->rf_head;
366: }
1.137 tobias 367: cvs_specified_date = -1;
1.136 tobias 368: } else if (cvs_cmdop == CVS_OP_DIFF) {
369: if (cf->file_ent->ce_status == CVS_ENT_ADDED)
370: diff_rev1 = NULL;
1.94 joris 371: else
1.136 tobias 372: diff_rev1 = cf->file_ent->ce_rev;
373: }
1.1 jfb 374:
1.136 tobias 375: if (cf->file_rcs == NULL)
376: diff_rev2 = NULL;
1.137 tobias 377: else if (rev2 != NULL || date2 != -1) {
378: cvs_specified_date = date2;
1.136 tobias 379: diff_rev2 = rcs_translate_tag(rev2, cf->file_rcs);
380: if (diff_rev2 == NULL && cvs_cmdop == CVS_OP_DIFF) {
1.137 tobias 381: if (rev2 != NULL) {
382: cvs_log(LP_ERR, "tag %s not in file %s", rev2,
383: cf->file_path);
1.143 tobias 384: goto cleanup;
385: } else if (Nflag) {
386: diff_rev2 = NULL;
1.137 tobias 387: } else {
1.139 tobias 388: gmtime_r(&cvs_specified_date, &datetm);
1.137 tobias 389: strftime(tbuf, sizeof(tbuf),
1.139 tobias 390: "%Y.%m.%d.%H.%M.%S", &datetm);
1.137 tobias 391: cvs_log(LP_ERR, "no revision for date %s in "
392: "file %s", tbuf, cf->file_path);
1.143 tobias 393: goto cleanup;
1.137 tobias 394: }
1.136 tobias 395: } else if (diff_rev2 == NULL && cvs_cmdop == CVS_OP_RDIFF &&
396: force_head) {
397: /* -f is not allowed for unknown symbols */
398: if ((diff_rev2 = rcsnum_parse(rev2)) == NULL)
399: fatal("no such tag %s", rev2);
400: rcsnum_free(diff_rev2);
1.91 joris 401:
1.136 tobias 402: diff_rev2 = cf->file_rcs->rf_head;
403: }
1.137 tobias 404: cvs_specified_date = -1;
1.136 tobias 405: } else if (cvs_cmdop == CVS_OP_RDIFF)
406: diff_rev2 = cf->file_rcs->rf_head;
407: else if (cf->file_ent->ce_status == CVS_ENT_REMOVED)
408: diff_rev2 = NULL;
1.114 joris 409:
1.136 tobias 410: if (diff_rev1 != NULL && diff_rev2 != NULL &&
411: rcsnum_cmp(diff_rev1, diff_rev2, 0) == 0)
412: goto cleanup;
1.125 tobias 413:
1.136 tobias 414: switch (cvs_cmdop) {
415: case CVS_OP_DIFF:
1.143 tobias 416: if (cf->file_status == FILE_UPTODATE && diff_rev1 != NULL &&
1.148 ! joris 417: diff_rev2 == NULL &&
1.136 tobias 418: rcsnum_cmp(diff_rev1, cf->file_rcsrev, 0) == 0)
419: goto cleanup;
420: break;
421: case CVS_OP_RDIFF:
422: if (diff_rev1 == NULL && diff_rev2 == NULL)
423: goto cleanup;
424: break;
425: }
426:
427: cvs_printf("Index: %s\n", cf->file_path);
428: if (cvs_cmdop == CVS_OP_DIFF)
429: cvs_printf("%s\nRCS file: %s\n", RCS_DIFF_DIV,
430: cf->file_rcs != NULL ? cf->file_rpath : cf->file_path);
431:
432: if (diff_rev1 != NULL) {
433: if (cvs_cmdop == CVS_OP_DIFF && diff_rev1 != NULL) {
434: (void)rcsnum_tostr(diff_rev1, rbuf, sizeof(rbuf));
435: cvs_printf("retrieving revision %s\n", rbuf);
1.125 tobias 436: }
1.136 tobias 437:
438: tv[0].tv_sec = rcs_rev_getdate(cf->file_rcs, diff_rev1);
439: tv[0].tv_usec = 0;
440: tv[1] = tv[0];
441:
442: (void)xasprintf(&p1, "%s/diff1.XXXXXXXXXX", cvs_tmpdir);
443: fd1 = rcs_rev_write_stmp(cf->file_rcs, diff_rev1, p1, 0);
444: if (futimes(fd1, tv) == -1)
445: fatal("cvs_diff_local: utimes failed");
1.94 joris 446: }
1.91 joris 447:
1.136 tobias 448: if (diff_rev2 != NULL) {
449: if (cvs_cmdop == CVS_OP_DIFF && rev2 != NULL) {
450: (void)rcsnum_tostr(diff_rev2, rbuf, sizeof(rbuf));
451: cvs_printf("retrieving revision %s\n", rbuf);
452: }
1.91 joris 453:
454: tv2[0].tv_sec = rcs_rev_getdate(cf->file_rcs, diff_rev2);
455: tv2[0].tv_usec = 0;
456: tv2[1] = tv2[0];
1.114 joris 457:
1.136 tobias 458: (void)xasprintf(&p2, "%s/diff2.XXXXXXXXXX", cvs_tmpdir);
1.131 joris 459: fd2 = rcs_rev_write_stmp(cf->file_rcs, diff_rev2, p2, 0);
460: if (futimes(fd2, tv2) == -1)
1.125 tobias 461: fatal("cvs_diff_local: utimes failed");
1.145 joris 462: } else if (cvs_cmdop == CVS_OP_DIFF &&
463: (cf->file_flags & FILE_ON_DISK) &&
1.136 tobias 464: cf->file_ent->ce_status != CVS_ENT_REMOVED) {
465: if (fstat(cf->fd, &st) == -1)
466: fatal("fstat failed %s", strerror(errno));
467: b1 = cvs_buf_load_fd(cf->fd);
1.125 tobias 468:
1.136 tobias 469: tv2[0].tv_sec = st.st_mtime;
470: tv2[0].tv_usec = 0;
471: tv2[1] = tv2[0];
1.121 joris 472:
1.136 tobias 473: (void)xasprintf(&p2, "%s/diff2.XXXXXXXXXX", cvs_tmpdir);
474: fd2 = cvs_buf_write_stmp(b1, p2, tv2);
475: cvs_buf_free(b1);
1.17 jfb 476: }
477:
1.136 tobias 478: switch (cvs_cmdop) {
479: case CVS_OP_DIFF:
1.125 tobias 480: cvs_printf("%s", diffargs);
481:
1.136 tobias 482: if (rev1 != NULL && diff_rev1 != NULL) {
483: (void)rcsnum_tostr(diff_rev1, rbuf, sizeof(rbuf));
1.125 tobias 484: cvs_printf(" -r%s", rbuf);
485:
1.136 tobias 486: if (rev2 != NULL && diff_rev2 != NULL) {
1.125 tobias 487: (void)rcsnum_tostr(diff_rev2, rbuf,
488: sizeof(rbuf));
489: cvs_printf(" -r%s", rbuf);
490: }
491: }
1.1 jfb 492:
1.125 tobias 493: if (diff_rev2 == NULL)
1.136 tobias 494: cvs_printf(" %s", cf->file_path);
1.130 tobias 495: cvs_printf("\n");
1.136 tobias 496: break;
497: case CVS_OP_RDIFF:
1.125 tobias 498: cvs_printf("diff ");
499: switch (diff_format) {
500: case D_CONTEXT:
501: cvs_printf("-c ");
502: break;
503: case D_RCSDIFF:
504: cvs_printf("-n ");
505: break;
506: case D_UNIFIED:
507: cvs_printf("-u ");
508: break;
509: default:
510: break;
511: }
512: if (diff_rev1 == NULL) {
513: cvs_printf("%s ", CVS_PATH_DEVNULL);
514: } else {
515: (void)rcsnum_tostr(diff_rev1, rbuf, sizeof(rbuf));
516: cvs_printf("%s:%s ", cf->file_path, rbuf);
517: }
1.1 jfb 518:
1.125 tobias 519: if (diff_rev2 == NULL) {
520: cvs_printf("%s:removed\n", cf->file_path);
521: } else {
522: (void)rcsnum_tostr(diff_rev2 != NULL ? diff_rev2 :
523: cf->file_rcs->rf_head, rbuf, sizeof(rbuf));
524: cvs_printf("%s:%s\n", cf->file_path, rbuf);
1.94 joris 525: }
1.136 tobias 526: break;
1.1 jfb 527: }
528:
1.136 tobias 529: if (fd1 == -1) {
530: if ((fd1 = open(CVS_PATH_DEVNULL, O_RDONLY, 0)) == -1)
531: fatal("cannot open %s", CVS_PATH_DEVNULL);
1.114 joris 532: }
1.136 tobias 533: if (fd2 == -1) {
534: if ((fd2 = open(CVS_PATH_DEVNULL, O_RDONLY, 0)) == -1)
535: fatal("cannot open %s", CVS_PATH_DEVNULL);
536: }
1.111 xsa 537:
1.136 tobias 538: if (cvs_diffreg(p1 != NULL ? cf->file_path : CVS_PATH_DEVNULL,
539: p2 != NULL ? cf->file_path : CVS_PATH_DEVNULL, fd1, fd2, NULL)
540: == D_ERROR)
1.111 xsa 541: fatal("cvs_diff_local: failed to get RCS patch");
1.131 joris 542:
543: close(fd1);
544: close(fd2);
1.58 niallo 545:
1.91 joris 546: cvs_worklist_run(&temp_files, cvs_worklist_unlink);
1.111 xsa 547:
548: if (p1 != NULL)
549: xfree(p1);
550: if (p2 != NULL)
551: xfree(p2);
1.101 joris 552:
1.136 tobias 553: cleanup:
554: if (diff_rev1 != NULL &&
555: (cf->file_rcs == NULL || diff_rev1 != cf->file_rcs->rf_head) &&
556: (cf->file_ent == NULL || diff_rev1 != cf->file_ent->ce_rev))
557: xfree(diff_rev1);
558: diff_rev1 = NULL;
1.94 joris 559:
1.136 tobias 560: if (diff_rev2 != NULL &&
561: (cf->file_rcs == NULL || diff_rev2 != cf->file_rcs->rf_head))
562: xfree(diff_rev2);
563: diff_rev2 = NULL;
1.1 jfb 564: }