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