Annotation of src/usr.bin/cvs/tag.c, Revision 1.14
1.14 ! jfb 1: /* $OpenBSD: tag.c,v 1.13 2005/04/18 21:02:50 jfb Exp $ */
1.1 jfb 2: /*
3: * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
1.5 joris 4: * Copyright (c) 2004 Joris Vink <joris@openbsd.org>
1.1 jfb 5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: *
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. The name of the author may not be used to endorse or promote products
14: * derived from this software without specific prior written permission.
15: *
16: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18: * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
19: * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26: */
27:
28: #include <sys/types.h>
29:
30: #include <errno.h>
31: #include <stdio.h>
32: #include <stdlib.h>
33: #include <string.h>
34:
35: #include "cvs.h"
36: #include "log.h"
37: #include "proto.h"
38:
39:
1.14 ! jfb 40: static int cvs_tag_local (CVSFILE *, void *);
! 41: static int cvs_tag_remote (CVSFILE *, void *);
! 42: static int cvs_tag_options (char *, int, char **, int *);
! 43: static int cvs_tag_sendflags (struct cvsroot *);
! 44:
! 45: static char *tag_name = NULL;
! 46: static char *tag_date = NULL;
! 47: static char *tag_oldname = NULL;
! 48: static int tag_branch = 0;
! 49: static int tag_delete = 0;
! 50: static int tag_forcehead = 0;
1.7 joris 51:
52: struct cvs_cmd_info cvs_tag = {
53: cvs_tag_options,
54: cvs_tag_sendflags,
1.14 ! jfb 55: cvs_tag_remote,
1.7 joris 56: NULL, NULL,
57: CF_SORT | CF_IGNORE | CF_RECURSE,
58: CVS_REQ_TAG,
1.14 ! jfb 59: CVS_CMD_ALLOWSPEC | CVS_CMD_SENDDIR
1.7 joris 60: };
1.1 jfb 61:
1.14 ! jfb 62: static int
1.7 joris 63: cvs_tag_options(char *opt, int argc, char **argv, int *arg)
1.1 jfb 64: {
1.7 joris 65: int ch;
1.1 jfb 66:
1.14 ! jfb 67: tag_date = tag_oldname = NULL;
1.1 jfb 68:
1.7 joris 69: while ((ch = getopt(argc, argv, opt)) != -1) {
1.1 jfb 70: switch (ch) {
71: case 'b':
1.14 ! jfb 72: tag_branch = 1;
1.1 jfb 73: break;
74: case 'd':
1.14 ! jfb 75: tag_delete = 1;
! 76: break;
! 77: case 'f':
! 78: tag_forcehead = 1;
1.1 jfb 79: break;
1.3 jfb 80: case 'D':
1.14 ! jfb 81: tag_date = optarg;
1.3 jfb 82: break;
1.1 jfb 83: case 'l':
1.7 joris 84: cvs_tag.file_flags &= ~CF_RECURSE;
1.1 jfb 85: break;
86: case 'r':
1.14 ! jfb 87: tag_oldname = optarg;
1.1 jfb 88: break;
89: default:
1.11 joris 90: return (CVS_EX_USAGE);
1.1 jfb 91: }
92: }
93:
1.7 joris 94: *arg = optind;
1.1 jfb 95: argc -= optind;
96: argv += optind;
97:
98: if (argc == 0) {
1.11 joris 99: return (CVS_EX_USAGE);
1.1 jfb 100: } else {
1.14 ! jfb 101: tag_name = argv[0];
1.1 jfb 102: argc--;
103: argv++;
1.7 joris 104: *arg += 1;
1.1 jfb 105: }
106:
1.14 ! jfb 107: if (tag_branch && tag_delete) {
1.1 jfb 108: cvs_log(LP_WARN, "ignoring -b with -d options");
1.14 ! jfb 109: tag_branch = 0;
1.1 jfb 110: }
111:
1.14 ! jfb 112: if (tag_delete && tag_oldname)
! 113: tag_oldname = NULL;
1.1 jfb 114:
1.14 ! jfb 115: if (tag_delete && tag_date)
! 116: tag_date = NULL;
1.3 jfb 117:
1.14 ! jfb 118: if (tag_oldname != NULL && tag_date != NULL) {
1.3 jfb 119: cvs_log(LP_ERROR, "-r and -D options are mutually exclusive");
1.11 joris 120: return (CVS_EX_USAGE);
1.3 jfb 121: }
122:
1.7 joris 123: return (0);
124: }
125:
1.14 ! jfb 126: static int
1.7 joris 127: cvs_tag_sendflags(struct cvsroot *root)
128: {
1.14 ! jfb 129: if (tag_branch && (cvs_sendarg(root, "-b", 0) < 0))
1.11 joris 130: return (CVS_EX_PROTO);
1.7 joris 131:
1.14 ! jfb 132: if (tag_delete && (cvs_sendarg(root, "-d", 0) < 0))
1.11 joris 133: return (CVS_EX_PROTO);
1.1 jfb 134:
1.14 ! jfb 135: if (tag_oldname) {
1.7 joris 136: if ((cvs_sendarg(root, "-r", 0) < 0) ||
1.14 ! jfb 137: (cvs_sendarg(root, tag_oldname, 0) < 0))
1.11 joris 138: return (CVS_EX_PROTO);
1.1 jfb 139: }
140:
1.14 ! jfb 141: if (tag_date) {
1.7 joris 142: if ((cvs_sendarg(root, "-D", 0) < 0) ||
1.14 ! jfb 143: (cvs_sendarg(root, tag_date, 0) < 0))
1.11 joris 144: return (CVS_EX_PROTO);
1.1 jfb 145: }
1.7 joris 146:
1.14 ! jfb 147: if (cvs_sendarg(root, tag_name, 0) < 0)
1.11 joris 148: return (CVS_EX_PROTO);
1.1 jfb 149:
150: return (0);
151: }
152:
153:
154: /*
1.14 ! jfb 155: * cvs_tag_remote()
1.1 jfb 156: *
157: * Get the status of a single file.
158: */
1.14 ! jfb 159: static int
! 160: cvs_tag_remote(CVSFILE *cfp, void *arg)
1.1 jfb 161: {
1.14 ! jfb 162: int ret;
! 163: char fpath[MAXPATHLEN];
1.1 jfb 164: struct cvsroot *root;
165:
166: ret = 0;
167: root = CVS_DIR_ROOT(cfp);
168:
1.14 ! jfb 169: if (cfp->cf_type == DT_DIR) {
! 170: ret = cvs_senddir(root, cfp);
! 171: return (ret);
! 172: }
! 173:
! 174: if (cvs_sendentry(root, cfp) < 0) {
! 175: return (CVS_EX_PROTO);
1.1 jfb 176: }
177:
178: cvs_file_getpath(cfp, fpath, sizeof(fpath));
179:
1.14 ! jfb 180: switch (cfp->cf_cvstat) {
! 181: case CVS_FST_UNKNOWN:
! 182: ret = cvs_sendreq(root, CVS_REQ_QUESTIONABLE, cfp->cf_name);
! 183: break;
! 184: case CVS_FST_UPTODATE:
! 185: ret = cvs_sendreq(root, CVS_REQ_UNCHANGED, cfp->cf_name);
! 186: break;
! 187: case CVS_FST_MODIFIED:
! 188: ret = cvs_sendreq(root, CVS_REQ_ISMODIFIED, cfp->cf_name);
! 189: default:
! 190: break;
! 191: }
! 192:
! 193: return (ret);
! 194: }
! 195:
! 196:
! 197: static int
! 198: cvs_tag_local(CVSFILE *cf, void *arg)
! 199: {
! 200: int len;
! 201: char *repo, fpath[MAXPATHLEN], rcspath[MAXPATHLEN];
! 202: struct cvsroot *root;
! 203: RCSFILE *rf;
! 204: RCSNUM *tag_rev;
! 205:
! 206: cvs_file_getpath(cf, fpath, sizeof(fpath));
! 207:
! 208: if (cf->cf_cvstat == CVS_FST_UNKNOWN) {
! 209: cvs_log(LP_WARN, "I know nothing about %s", fpath);
! 210: return (0);
! 211: }
1.1 jfb 212:
1.14 ! jfb 213: repo = CVS_DIR_REPO(cf);
! 214: root = CVS_DIR_ROOT(cf);
1.1 jfb 215:
1.14 ! jfb 216: len = snprintf(rcspath, sizeof(rcspath), "%s/%s/%s%s",
! 217: root->cr_dir, repo, cf->cf_name, RCS_FILE_EXT);
! 218: if (len == -1 || len >= (int)sizeof(rcspath)) {
! 219: errno = ENAMETOOLONG;
! 220: cvs_log(LP_ERRNO, "%s", rcspath);
! 221: return (-1);
! 222: }
1.1 jfb 223:
1.14 ! jfb 224: rf = rcs_open(rcspath, RCS_READ|RCS_WRITE);
! 225: if (rf == NULL) {
! 226: cvs_log(LP_ERR, "failed to open %s: %s", rcspath,
! 227: rcs_errstr(rcs_errno));
! 228: return (-1);
! 229: }
1.1 jfb 230:
1.14 ! jfb 231: if (rcs_sym_add(rf, tag_name, tag_rev) < 0) {
! 232: cvs_log(LP_ERR, "failed to tag %s: %s", rcspath,
! 233: rcs_errstr(rcs_errno));
1.1 jfb 234: }
235:
1.14 ! jfb 236: rcs_close(rf);
! 237: return (0);
1.1 jfb 238: }