1 /* $OpenBSD: getlog.c,v 1.13 2004/12/21 18:32:10 jfb Exp $ */ 2 /* 3 * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. The name of the author may not be used to endorse or promote products 13 * derived from this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 16 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 17 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 18 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <sys/param.h> 28 29 #include <stdlib.h> 30 #include <stdio.h> 31 #include <unistd.h> 32 #include <errno.h> 33 #include <string.h> 34 #include <paths.h> 35 #include <sysexits.h> 36 37 #include "cvs.h" 38 #include "log.h" 39 #include "file.h" 40 #include "proto.h" 41 42 43 #define CVS_GLOG_RFONLY 0x01 44 #define CVS_GLOG_HDONLY 0x02 45 46 47 #define CVS_GETLOG_REVSEP "----------------------------" 48 #define CVS_GETLOG_REVEND \ 49 "=============================================================================" 50 51 #ifdef notyet 52 static void cvs_getlog_print (const char *, RCSFILE *, u_int); 53 #endif 54 static int cvs_getlog_file (CVSFILE *, void *); 55 56 57 58 /* 59 * cvs_getlog() 60 * 61 * Implement the `cvs log' command. 62 */ 63 int 64 cvs_getlog(int argc, char **argv) 65 { 66 int i, rfonly, honly, flags; 67 struct cvsroot *root; 68 69 flags = CF_RECURSE; 70 rfonly = 0; 71 honly = 0; 72 73 while ((i = getopt(argc, argv, "d:hlRr:")) != -1) { 74 switch (i) { 75 case 'd': 76 break; 77 case 'h': 78 honly = 1; 79 break; 80 case 'l': 81 flags &= ~CF_RECURSE; 82 break; 83 case 'R': 84 rfonly = 1; 85 break; 86 case 'r': 87 break; 88 default: 89 return (EX_USAGE); 90 } 91 } 92 93 argc -= optind; 94 argv += optind; 95 96 if (argc == 0) 97 cvs_files = cvs_file_get(".", flags); 98 else 99 cvs_files = cvs_file_getspec(argv, argc, flags); 100 if (cvs_files == NULL) 101 return (EX_DATAERR); 102 103 root = CVS_DIR_ROOT(cvs_files); 104 if (root == NULL) { 105 cvs_log(LP_ERR, 106 "No CVSROOT specified! Please use the `-d' option"); 107 cvs_log(LP_ERR, 108 "or set the CVSROOT environment variable."); 109 return (EX_USAGE); 110 } 111 112 if ((root->cr_method != CVS_METHOD_LOCAL) && (cvs_connect(root) < 0)) 113 return (EX_PROTOCOL); 114 115 cvs_file_examine(cvs_files, cvs_getlog_file, NULL); 116 117 if (root->cr_method != CVS_METHOD_LOCAL) { 118 cvs_senddir(root, cvs_files); 119 if (argc > 0) { 120 for (i = 0; i < argc; i++) 121 cvs_sendarg(root, argv[i], 0); 122 } 123 cvs_sendreq(root, CVS_REQ_LOG, NULL); 124 } 125 126 return (0); 127 } 128 129 130 /* 131 * cvs_getlog_file() 132 * 133 * Diff a single file. 134 */ 135 static int 136 cvs_getlog_file(CVSFILE *cf, void *arg) 137 { 138 int ret; 139 char *repo, fpath[MAXPATHLEN]; 140 RCSFILE *rf; 141 struct cvsroot *root; 142 struct cvs_ent *entp; 143 144 ret = 0; 145 rf = NULL; 146 root = CVS_DIR_ROOT(cf); 147 repo = CVS_DIR_REPO(cf); 148 149 if (cf->cf_type == DT_DIR) { 150 if (root->cr_method != CVS_METHOD_LOCAL) { 151 if (cf->cf_cvstat == CVS_FST_UNKNOWN) 152 ret = cvs_sendreq(root, CVS_REQ_QUESTIONABLE, 153 CVS_FILE_NAME(cf)); 154 else 155 ret = cvs_senddir(root, cf); 156 } 157 158 return (ret); 159 } 160 161 cvs_file_getpath(cf, fpath, sizeof(fpath)); 162 entp = cvs_ent_getent(fpath); 163 164 if (root->cr_method != CVS_METHOD_LOCAL) { 165 if ((entp != NULL) && (cvs_sendentry(root, entp) < 0)) { 166 cvs_ent_free(entp); 167 return (-1); 168 } 169 170 switch (cf->cf_cvstat) { 171 case CVS_FST_UNKNOWN: 172 ret = cvs_sendreq(root, CVS_REQ_QUESTIONABLE, 173 CVS_FILE_NAME(cf)); 174 break; 175 case CVS_FST_UPTODATE: 176 ret = cvs_sendreq(root, CVS_REQ_UNCHANGED, 177 CVS_FILE_NAME(cf)); 178 break; 179 case CVS_FST_ADDED: 180 case CVS_FST_MODIFIED: 181 ret = cvs_sendreq(root, CVS_REQ_ISMODIFIED, 182 CVS_FILE_NAME(cf)); 183 break; 184 default: 185 break; 186 } 187 } else { 188 if (cf->cf_cvstat == CVS_FST_UNKNOWN) { 189 cvs_printf("? %s\n", fpath); 190 return (0); 191 } 192 193 snprintf(fpath, sizeof(fpath), "%s/%s/%s%s", 194 root->cr_dir, repo, CVS_FILE_NAME(cf), RCS_FILE_EXT); 195 196 rf = rcs_open(fpath, RCS_MODE_READ); 197 if (rf == NULL) { 198 cvs_ent_free(entp); 199 return (-1); 200 } 201 202 rcs_close(rf); 203 } 204 205 if (entp != NULL) 206 cvs_ent_free(entp); 207 return (ret); 208 } 209 210 #ifdef notyet 211 static void 212 cvs_getlog_print(const char *file, RCSFILE *rfp, u_int flags) 213 { 214 char numbuf[64], datebuf[64], *sp; 215 struct rcs_delta *rdp; 216 217 cvs_printf("RCS file: %s\nWorking file: %s\n", 218 rfp->rf_path, file); 219 cvs_printf("Working file: %s\n", (char *)NULL); 220 cvs_printf("head: %s\nbranch:\nlocks:\naccess list:\n"); 221 cvs_printf("symbolic names:\nkeyword substitutions:\n"); 222 cvs_printf("total revisions: %u;\tselected revisions: %u\n", 1, 1); 223 224 cvs_printf("description:\n"); 225 226 for (;;) { 227 cvs_printf(CVS_GETLOG_REVSEP "\n"); 228 rcsnum_tostr(rdp->rd_num, numbuf, sizeof(numbuf)); 229 cvs_printf("revision %s\n", numbuf); 230 cvs_printf("date: %d/%02d/%d %02d:%02d:%02d; author: %s;" 231 " state: %s; lines:", 232 rdp->rd_date.tm_year, rdp->rd_date.tm_mon + 1, 233 rdp->rd_date.tm_mday, rdp->rd_date.tm_hour, 234 rdp->rd_date.tm_min, rdp->rd_date.tm_sec, 235 rdp->rd_author, rdp->rd_state); 236 } 237 238 cvs_printf(CVS_GETLOG_REVEND "\n"); 239 } 240 #endif 241