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