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