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