1 /* $OpenBSD: annotate.c,v 1.3 2004/12/21 18:32:09 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 #include <sysexits.h> 37 38 #include "cvs.h" 39 #include "rcs.h" 40 #include "log.h" 41 #include "proto.h" 42 43 44 int cvs_annotate_file (CVSFILE *, void *); 45 int cvs_annotate_prune (CVSFILE *, void *); 46 47 48 /* 49 * cvs_annotate() 50 * 51 * Handle the `cvs annotate' command. 52 * Returns 0 on success, or the appropriate exit code on error. 53 */ 54 int 55 cvs_annotate(int argc, char **argv) 56 { 57 int i, ch, flags; 58 char *date, *rev; 59 struct cvsroot *root; 60 61 date = NULL; 62 rev = NULL; 63 flags = CF_SORT|CF_RECURSE|CF_IGNORE|CF_NOSYMS; 64 65 while ((ch = getopt(argc, argv, "D:FflRr:")) != -1) { 66 switch (ch) { 67 case 'D': 68 date = optarg; 69 break; 70 case 'l': 71 flags &= ~CF_RECURSE; 72 break; 73 case 'R': 74 flags |= CF_RECURSE; 75 break; 76 case 'r': 77 break; 78 default: 79 return (EX_USAGE); 80 } 81 } 82 83 argc -= optind; 84 argv += optind; 85 86 if (argc == 0) { 87 cvs_files = cvs_file_get(".", flags); 88 } else { 89 /* don't perform ignore on explicitly listed files */ 90 flags &= ~(CF_IGNORE | CF_RECURSE | CF_SORT); 91 cvs_files = cvs_file_getspec(argv, argc, flags); 92 } 93 if (cvs_files == NULL) 94 return (EX_DATAERR); 95 96 root = CVS_DIR_ROOT(cvs_files); 97 if (root == NULL) { 98 cvs_log(LP_ERR, 99 "No CVSROOT specified! Please use the `-d' option"); 100 cvs_log(LP_ERR, 101 "or set the CVSROOT environment variable."); 102 return (EX_USAGE); 103 } 104 105 if (root->cr_method != CVS_METHOD_LOCAL) { 106 if (cvs_connect(root) < 0) 107 return (EX_PROTOCOL); 108 if (rev != NULL) { 109 if ((cvs_sendarg(root, "-r", 0) < 0) || 110 (cvs_sendarg(root, rev, 0) < 0)) 111 return (EX_PROTOCOL); 112 } 113 if (date != NULL) { 114 if ((cvs_sendarg(root, "-D", 0) < 0) || 115 (cvs_sendarg(root, date, 0) < 0)) 116 return (EX_PROTOCOL); 117 } 118 } 119 120 cvs_file_examine(cvs_files, cvs_annotate_file, NULL); 121 122 123 if (root->cr_method != CVS_METHOD_LOCAL) { 124 if (cvs_senddir(root, cvs_files) < 0) 125 return (EX_PROTOCOL); 126 for (i = 0; i < argc; i++) 127 if (cvs_sendarg(root, argv[i], 0) < 0) 128 return (EX_PROTOCOL); 129 if (cvs_sendreq(root, CVS_REQ_ANNOTATE, NULL) < 0) 130 return (EX_PROTOCOL); 131 } 132 133 return (0); 134 } 135 136 137 /* 138 * cvs_annotate_file() 139 * 140 * Annotate a single file. 141 */ 142 int 143 cvs_annotate_file(CVSFILE *cf, void *arg) 144 { 145 int ret; 146 char fpath[MAXPATHLEN]; 147 struct cvsroot *root; 148 struct cvs_ent *entp; 149 150 ret = 0; 151 root = CVS_DIR_ROOT(cf); 152 153 if (cf->cf_type == DT_DIR) { 154 if (root->cr_method != CVS_METHOD_LOCAL) { 155 if (cf->cf_cvstat == CVS_FST_UNKNOWN) 156 ret = cvs_sendreq(root, CVS_REQ_QUESTIONABLE, 157 CVS_FILE_NAME(cf)); 158 else 159 ret = cvs_senddir(root, cf); 160 } 161 162 return (ret); 163 } 164 165 cvs_file_getpath(cf, fpath, sizeof(fpath)); 166 entp = cvs_ent_getent(fpath); 167 168 if (root->cr_method != CVS_METHOD_LOCAL) { 169 if ((entp != NULL) && (cvs_sendentry(root, entp) < 0)) { 170 cvs_ent_free(entp); 171 return (-1); 172 } 173 174 switch (cf->cf_cvstat) { 175 case CVS_FST_UNKNOWN: 176 ret = cvs_sendreq(root, CVS_REQ_QUESTIONABLE, 177 CVS_FILE_NAME(cf)); 178 break; 179 case CVS_FST_UPTODATE: 180 ret = cvs_sendreq(root, CVS_REQ_UNCHANGED, 181 CVS_FILE_NAME(cf)); 182 break; 183 case CVS_FST_ADDED: 184 case CVS_FST_MODIFIED: 185 ret = cvs_sendreq(root, CVS_REQ_ISMODIFIED, 186 CVS_FILE_NAME(cf)); 187 break; 188 default: 189 break; 190 } 191 } else { 192 if (cf->cf_cvstat == CVS_FST_UNKNOWN) { 193 cvs_printf("? %s\n", fpath); 194 return (0); 195 } 196 } 197 198 if (entp != NULL) 199 cvs_ent_free(entp); 200 return (ret); 201 } 202