1 /* $OpenBSD: annotate.c,v 1.11 2005/04/18 21:02:49 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 #include <sys/stat.h> 29 30 #include <errno.h> 31 #include <stdio.h> 32 #include <fcntl.h> 33 #include <stdlib.h> 34 #include <unistd.h> 35 #include <string.h> 36 37 #include "cvs.h" 38 #include "rcs.h" 39 #include "log.h" 40 #include "proto.h" 41 42 43 int cvs_annotate_file(CVSFILE *, void *); 44 int cvs_annotate_prune(CVSFILE *, void *); 45 int cvs_annotate_options(char *, int, char **, int *); 46 int cvs_annotate_sendflags(struct cvsroot *); 47 48 struct cvs_cmd_info cvs_annotate = { 49 cvs_annotate_options, 50 cvs_annotate_sendflags, 51 cvs_annotate_file, 52 NULL, NULL, 53 CF_SORT | CF_RECURSE | CF_IGNORE | CF_NOSYMS, 54 CVS_REQ_ANNOTATE, 55 CVS_CMD_ALLOWSPEC | CVS_CMD_SENDDIR | CVS_CMD_SENDARGS2 56 }; 57 58 static char *date, *rev; 59 static int usehead; 60 61 int 62 cvs_annotate_options(char *opt, int argc, char **argv, int *arg) 63 { 64 int ch; 65 66 usehead = 0; 67 date = NULL; 68 rev = NULL; 69 70 while ((ch = getopt(argc, argv, opt)) != -1) { 71 switch (ch) { 72 case 'D': 73 date = optarg; 74 break; 75 case 'f': 76 usehead = 1; 77 break; 78 case 'l': 79 cvs_annotate.file_flags &= ~CF_RECURSE; 80 break; 81 case 'R': 82 cvs_annotate.file_flags |= CF_RECURSE; 83 break; 84 case 'r': 85 rev = optarg; 86 break; 87 default: 88 return (CVS_EX_USAGE); 89 } 90 } 91 92 if ((date != NULL) && (rev != NULL)) { 93 cvs_log(LP_ERR, 94 "the -D and -d arguments are mutually exclusive"); 95 return (CVS_EX_USAGE); 96 } 97 98 *arg = optind; 99 return (0); 100 } 101 102 int 103 cvs_annotate_sendflags(struct cvsroot *root) 104 { 105 if (usehead && (cvs_sendarg(root, "-f", 0) < 0)) 106 return (CVS_EX_PROTO); 107 108 if (rev != NULL) { 109 if ((cvs_sendarg(root, "-r", 0) < 0) || 110 (cvs_sendarg(root, rev, 0) < 0)) 111 return (CVS_EX_PROTO); 112 } 113 114 if (date != NULL) { 115 if ((cvs_sendarg(root, "-D", 0) < 0) || 116 (cvs_sendarg(root, date, 0) < 0)) 117 return (CVS_EX_PROTO); 118 } 119 120 return (0); 121 } 122 123 /* 124 * cvs_annotate_file() 125 * 126 * Annotate a single file. 127 */ 128 int 129 cvs_annotate_file(CVSFILE *cf, void *arg) 130 { 131 int ret; 132 char fpath[MAXPATHLEN]; 133 struct cvsroot *root; 134 135 ret = 0; 136 root = CVS_DIR_ROOT(cf); 137 138 if (cf->cf_type == DT_DIR) { 139 if (root->cr_method != CVS_METHOD_LOCAL) { 140 if (cf->cf_cvstat == CVS_FST_UNKNOWN) 141 ret = cvs_sendreq(root, CVS_REQ_QUESTIONABLE, 142 CVS_FILE_NAME(cf)); 143 else 144 ret = cvs_senddir(root, cf); 145 } 146 147 return (ret); 148 } 149 150 cvs_file_getpath(cf, fpath, sizeof(fpath)); 151 152 if (root->cr_method != CVS_METHOD_LOCAL) { 153 if (cvs_sendentry(root, cf) < 0) { 154 return (CVS_EX_PROTO); 155 } 156 157 switch (cf->cf_cvstat) { 158 case CVS_FST_UNKNOWN: 159 ret = cvs_sendreq(root, CVS_REQ_QUESTIONABLE, 160 CVS_FILE_NAME(cf)); 161 break; 162 case CVS_FST_UPTODATE: 163 ret = cvs_sendreq(root, CVS_REQ_UNCHANGED, 164 CVS_FILE_NAME(cf)); 165 break; 166 case CVS_FST_ADDED: 167 case CVS_FST_MODIFIED: 168 ret = cvs_sendreq(root, CVS_REQ_ISMODIFIED, 169 CVS_FILE_NAME(cf)); 170 break; 171 default: 172 break; 173 } 174 } else { 175 if (cf->cf_cvstat == CVS_FST_UNKNOWN) { 176 cvs_printf("? %s\n", fpath); 177 return (0); 178 } 179 } 180 181 return (ret); 182 } 183