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