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