Annotation of src/usr.bin/cvs/diff.c, Revision 1.91
1.91 ! joris 1: /* $OpenBSD$ */
1.1 jfb 2: /*
1.91 ! joris 3: * Copyright (c) 2006 Joris Vink <joris@openbsd.org>
1.1 jfb 4: *
1.91 ! joris 5: * Permission to use, copy, modify, and distribute this software for any
! 6: * purpose with or without fee is hereby granted, provided that the above
! 7: * copyright notice and this permission notice appear in all copies.
! 8: *
! 9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1.1 jfb 16: */
17:
1.75 xsa 18: #include "includes.h"
1.1 jfb 19:
20: #include "cvs.h"
1.56 niallo 21: #include "diff.h"
1.1 jfb 22: #include "log.h"
1.4 jfb 23: #include "proto.h"
1.86 joris 24:
1.91 ! joris 25: int cvs_diff(int, char **);
! 26: void cvs_diff_local(struct cvs_file *);
1.46 xsa 27:
1.36 jfb 28: struct cvs_cmd cvs_cmd_diff = {
29: CVS_OP_DIFF, CVS_REQ_DIFF, "diff",
30: { "di", "dif" },
31: "Show differences between revisions",
1.43 xsa 32: "[-cilNnpu] [[-D date] [-r rev] [-D date2 | -r rev2]] "
33: "[-k mode] [file ...]",
34: "cD:iklNnpr:Ru",
1.36 jfb 35: NULL,
1.91 ! joris 36: cvs_diff
1.36 jfb 37: };
38:
1.91 ! joris 39: int
! 40: cvs_diff(int argc, char **argv)
1.1 jfb 41: {
1.23 joris 42: int ch;
1.91 ! joris 43: char *arg = ".";
! 44: struct cvs_recursion cr;
1.1 jfb 45:
1.2 jfb 46: strlcpy(diffargs, argv[0], sizeof(diffargs));
1.1 jfb 47:
1.91 ! joris 48: while ((ch = getopt(argc, argv, cvs_cmd_diff.cmd_opts)) != -1) {
1.1 jfb 49: switch (ch) {
50: case 'c':
1.2 jfb 51: strlcat(diffargs, " -c", sizeof(diffargs));
1.58 niallo 52: diff_format = D_CONTEXT;
1.1 jfb 53: break;
1.33 jfb 54: case 'n':
55: strlcat(diffargs, " -n", sizeof(diffargs));
1.58 niallo 56: diff_format = D_RCSDIFF;
1.33 jfb 57: break;
1.1 jfb 58: case 'r':
1.91 ! joris 59: if (diff_rev1 == NULL) {
! 60: diff_rev1 = rcsnum_parse(optarg);
! 61: if (diff_rev1 == NULL)
! 62: fatal("rcsnum_parse failed");
! 63: } else if (diff_rev2 == NULL) {
! 64: diff_rev2 = rcsnum_parse(optarg);
! 65: if (diff_rev2 == NULL)
! 66: fatal("rcsnum_parse failed");
1.23 joris 67: } else {
1.91 ! joris 68: fatal("no more than 2 revisions/dates can"
! 69: " be specified");
1.1 jfb 70: }
1.32 joris 71: break;
1.1 jfb 72: case 'u':
1.2 jfb 73: strlcat(diffargs, " -u", sizeof(diffargs));
1.58 niallo 74: diff_format = D_UNIFIED;
1.1 jfb 75: break;
76: default:
1.91 ! joris 77: fatal("%s", cvs_cmd_diff.cmd_synopsis);
1.36 jfb 78: }
1.13 jfb 79: }
80:
1.91 ! joris 81: argc -= optind;
! 82: argv += optind;
1.1 jfb 83:
1.91 ! joris 84: cr.enterdir = NULL;
! 85: cr.leavedir = NULL;
! 86: cr.local = cvs_diff_local;
! 87: cr.remote = NULL;
1.7 jfb 88:
1.91 ! joris 89: if (argc > 0)
! 90: cvs_file_run(argc, argv, &cr);
1.82 ray 91: else
1.91 ! joris 92: cvs_file_run(1, &arg, &cr);
1.36 jfb 93:
94: return (0);
95: }
96:
1.91 ! joris 97: void
! 98: cvs_diff_local(struct cvs_file *cf)
1.36 jfb 99: {
1.91 ! joris 100: size_t len;
! 101: RCSNUM *r1;
1.36 jfb 102: BUF *b1, *b2;
1.91 ! joris 103: struct stat st;
1.69 niallo 104: struct timeval tv[2], tv2[2];
1.91 ! joris 105: char rbuf[16], p1[MAXPATHLEN], p2[MAXPATHLEN];
1.69 niallo 106:
1.91 ! joris 107: cvs_log(LP_TRACE, "cvs_diff_local(%s)", cf->file_path);
1.1 jfb 108:
1.91 ! joris 109: if (cf->file_type == CVS_DIR) {
1.46 xsa 110: if (verbosity > 1)
1.91 ! joris 111: cvs_log(LP_NOTICE, "Diffing inside %s", cf->file_path);
1.1 jfb 112: return;
113: }
114:
1.91 ! joris 115: cvs_file_classify(cf);
1.1 jfb 116:
1.91 ! joris 117: if (cf->file_status == FILE_LOST) {
! 118: cvs_log(LP_ERR, "cannot find file %s", cf->file_path);
1.1 jfb 119: return;
1.91 ! joris 120: } else if (cf->file_status == FILE_UNKNOWN) {
! 121: cvs_log(LP_ERR, "I know nothing about %s", cf->file_path);
1.1 jfb 122: return;
1.91 ! joris 123: } else if (cf->file_status == FILE_UPTODATE && diff_rev2 == NULL)
1.1 jfb 124: return;
125:
1.91 ! joris 126: diff_file = cf->file_path;
! 127: cvs_printf("Index: %s\n%s\nRCS file: %s\n", cf->file_path,
! 128: RCS_DIFF_DIV, cf->file_rpath);
1.1 jfb 129:
1.91 ! joris 130: if (diff_rev1 != NULL)
! 131: r1 = diff_rev1;
! 132: else
! 133: r1 = cf->file_ent->ce_rev;
1.1 jfb 134:
1.91 ! joris 135: diff_rev1 = r1;
! 136: rcsnum_tostr(r1, rbuf , sizeof(rbuf));
! 137: cvs_printf("retrieving revision %s\n", rbuf);
! 138: if ((b1 = rcs_getrev(cf->file_rcs, r1)) == NULL)
! 139: fatal("failed to retrieve revision %s", rbuf);
! 140:
! 141: tv[0].tv_sec = rcs_rev_getdate(cf->file_rcs, r1);
! 142: tv[0].tv_usec = 0;
! 143: tv[1] = tv[0];
! 144:
! 145: if (diff_rev2 != NULL) {
! 146: rcsnum_tostr(diff_rev2, rbuf, sizeof(rbuf));
! 147: cvs_printf("retrieving revision %s\n", rbuf);
! 148: if ((b2 = rcs_getrev(cf->file_rcs, diff_rev2)) == NULL)
! 149: fatal("failed to retrieve revision %s", rbuf);
! 150:
! 151: tv2[0].tv_sec = rcs_rev_getdate(cf->file_rcs, diff_rev2);
! 152: tv2[0].tv_usec = 0;
! 153: tv2[1] = tv2[0];
1.1 jfb 154: } else {
1.91 ! joris 155: if (fstat(cf->fd, &st) == -1)
! 156: fatal("fstat failed %s", strerror(errno));
! 157: if ((b2 = cvs_buf_load(cf->file_path, BUF_AUTOEXT)) == NULL)
! 158: fatal("failed to load %s", cf->file_path);
! 159:
! 160: st.st_mtime = cvs_hack_time(st.st_mtime, 1);
! 161: if (st.st_mtime == 0)
! 162: fatal("cvs_diff_local: to gmt failed");
1.1 jfb 163:
1.91 ! joris 164: tv2[0].tv_sec = st.st_mtime;
! 165: tv2[0].tv_usec = 0;
! 166: tv2[1] = tv2[0];
1.17 jfb 167: }
168:
1.91 ! joris 169: cvs_printf("%s", diffargs);
1.1 jfb 170:
1.91 ! joris 171: rcsnum_tostr(r1, rbuf, sizeof(rbuf));
! 172: cvs_printf(" -r%s", rbuf);
1.1 jfb 173:
1.91 ! joris 174: if (diff_rev2 != NULL) {
! 175: rcsnum_tostr(diff_rev2, rbuf, sizeof(rbuf));
! 176: cvs_printf(" -r%s", rbuf);
1.1 jfb 177: }
178:
1.91 ! joris 179: cvs_printf(" %s\n", cf->file_path);
1.1 jfb 180:
1.91 ! joris 181: len = strlcpy(p1, cvs_tmpdir, sizeof(p1));
! 182: if (len >= sizeof(p1))
! 183: fatal("cvs_diff_local: truncation");
1.1 jfb 184:
1.91 ! joris 185: len = strlcat(p1, "/diff1.XXXXXXXXXX", sizeof(p1));
! 186: if (len >= sizeof(p1))
! 187: fatal("cvs_diff_local: truncation");
1.1 jfb 188:
1.91 ! joris 189: cvs_buf_write_stmp(b1, p1, 0600, tv);
! 190: cvs_buf_free(b1);
1.1 jfb 191:
1.91 ! joris 192: len = strlcpy(p2, cvs_tmpdir, sizeof(p2));
! 193: if (len >= sizeof(p2))
! 194: fatal("cvs_diff_local: truncation");
! 195:
! 196: len = strlcat(p2, "/diff2.XXXXXXXXXX", sizeof(p2));
! 197: if (len >= sizeof(p2))
! 198: fatal("cvs_diff_local: truncation");
1.1 jfb 199:
1.91 ! joris 200: cvs_buf_write_stmp(b2, p2, 0600, tv2);
! 201: cvs_buf_free(b2);
1.58 niallo 202:
1.91 ! joris 203: cvs_diffreg(p1, p2, NULL);
! 204: cvs_worklist_run(&temp_files, cvs_worklist_unlink);
1.1 jfb 205: }