Annotation of src/usr.bin/cvs/tag.c, Revision 1.32
1.32 ! xsa 1: /* $OpenBSD: tag.c,v 1.31 2005/09/26 17:43:48 xsa 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.28 xsa 40: static int cvs_tag_init(struct cvs_cmd *, int, char **, int *);
41: static int cvs_tag_local(CVSFILE *, void *);
42: static int cvs_tag_remote(CVSFILE *, void *);
43: static int cvs_tag_pre_exec(struct cvsroot *);
1.14 jfb 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.21 xsa 51: static int tag_forcemove = 0;
1.7 joris 52:
1.17 jfb 53: struct cvs_cmd cvs_cmd_tag = {
54: CVS_OP_TAG, CVS_REQ_TAG, "tag",
55: { "ta", "freeze" },
56: "Add a symbolic tag to checked out version of files",
57: "[-bcdFflR] [-D date | -r rev] tagname ...",
58: "bcD:dFflRr:",
59: NULL,
1.7 joris 60: CF_SORT | CF_IGNORE | CF_RECURSE,
1.17 jfb 61: cvs_tag_init,
62: cvs_tag_pre_exec,
63: cvs_tag_remote,
64: cvs_tag_local,
65: NULL,
66: NULL,
67: CVS_CMD_ALLOWSPEC | CVS_CMD_SENDDIR
68: };
69:
70:
71: struct cvs_cmd cvs_cmd_rtag = {
72: CVS_OP_RTAG, CVS_REQ_TAG, "rtag",
1.30 xsa 73: { "rt", "rfreeze" },
1.17 jfb 74: "Add a symbolic tag to a module",
1.21 xsa 75: "[-abdFflnR] [-D date | -r rev] symbolic_tag modules ...",
76: "abD:fFflnRr:",
1.17 jfb 77: NULL,
78: CF_SORT | CF_IGNORE | CF_RECURSE,
79: cvs_tag_init,
80: cvs_tag_pre_exec,
81: cvs_tag_remote,
82: cvs_tag_local,
83: NULL,
84: NULL,
1.14 jfb 85: CVS_CMD_ALLOWSPEC | CVS_CMD_SENDDIR
1.7 joris 86: };
1.1 jfb 87:
1.14 jfb 88: static int
1.17 jfb 89: cvs_tag_init(struct cvs_cmd *cmd, int argc, char **argv, int *arg)
1.1 jfb 90: {
1.7 joris 91: int ch;
1.1 jfb 92:
1.14 jfb 93: tag_date = tag_oldname = NULL;
1.1 jfb 94:
1.17 jfb 95: while ((ch = getopt(argc, argv, cmd->cmd_opts)) != -1) {
1.1 jfb 96: switch (ch) {
97: case 'b':
1.14 jfb 98: tag_branch = 1;
1.1 jfb 99: break;
100: case 'd':
1.14 jfb 101: tag_delete = 1;
102: break;
1.21 xsa 103: case 'F':
104: tag_forcemove = 1;
105: break;
1.14 jfb 106: case 'f':
107: tag_forcehead = 1;
1.1 jfb 108: break;
1.3 jfb 109: case 'D':
1.14 jfb 110: tag_date = optarg;
1.3 jfb 111: break;
1.1 jfb 112: case 'l':
1.17 jfb 113: cmd->file_flags &= ~CF_RECURSE;
114: break;
115: case 'R':
116: cmd->file_flags |= CF_RECURSE;
1.1 jfb 117: break;
118: case 'r':
1.14 jfb 119: tag_oldname = optarg;
1.1 jfb 120: break;
121: default:
1.11 joris 122: return (CVS_EX_USAGE);
1.1 jfb 123: }
124: }
125:
1.7 joris 126: *arg = optind;
1.1 jfb 127: argc -= optind;
128: argv += optind;
129:
130: if (argc == 0) {
1.11 joris 131: return (CVS_EX_USAGE);
1.1 jfb 132: } else {
1.14 jfb 133: tag_name = argv[0];
1.1 jfb 134: argc--;
135: argv++;
1.7 joris 136: *arg += 1;
1.15 jfb 137: }
138:
139: if (!rcs_sym_check(tag_name)) {
140: cvs_log(LP_ABORT,
141: "tag `%s' must not contain the characters `%s'",
142: tag_name, RCS_SYM_INVALCHAR);
143: return (CVS_EX_BADTAG);
1.1 jfb 144: }
145:
1.31 xsa 146: if ((tag_branch == 1) && (tag_delete == 1)) {
1.1 jfb 147: cvs_log(LP_WARN, "ignoring -b with -d options");
1.14 jfb 148: tag_branch = 0;
1.1 jfb 149: }
150:
1.31 xsa 151: if ((tag_delete == 1) && (tag_oldname != NULL))
1.14 jfb 152: tag_oldname = NULL;
1.1 jfb 153:
1.31 xsa 154: if ((tag_delete == 1) && (tag_date != NULL))
1.14 jfb 155: tag_date = NULL;
1.3 jfb 156:
1.31 xsa 157: if ((tag_oldname != NULL) && (tag_date != NULL)) {
1.20 xsa 158: cvs_log(LP_ERR, "the -D and -r options are mutually exclusive");
1.11 joris 159: return (CVS_EX_USAGE);
1.3 jfb 160: }
161:
1.7 joris 162: return (0);
163: }
164:
1.14 jfb 165: static int
1.17 jfb 166: cvs_tag_pre_exec(struct cvsroot *root)
1.7 joris 167: {
1.17 jfb 168: if (root->cr_method != CVS_METHOD_LOCAL) {
1.32 ! xsa 169: if ((tag_branch == 1) && (cvs_sendarg(root, "-b", 0) < 0))
1.17 jfb 170: return (CVS_EX_PROTO);
171:
1.32 ! xsa 172: if ((tag_delete ==1) && (cvs_sendarg(root, "-d", 0) < 0))
1.17 jfb 173: return (CVS_EX_PROTO);
1.7 joris 174:
1.32 ! xsa 175: if ((tag_forcemove == 1) && (cvs_sendarg(root, "-F", 0) < 0))
1.21 xsa 176: return (CVS_EX_PROTO);
177:
1.32 ! xsa 178: if ((tag_forcehead == 1) && (cvs_sendarg(root, "-f", 0) < 0))
1.21 xsa 179: return (CVS_EX_PROTO);
180:
1.32 ! xsa 181: if ((tag_oldname != NULL) &&
! 182: ((cvs_sendarg(root, "-r", 0) < 0) ||
1.21 xsa 183: (cvs_sendarg(root, tag_oldname, 0) < 0)))
1.17 jfb 184: return (CVS_EX_PROTO);
1.1 jfb 185:
1.32 ! xsa 186: if ((tag_date != NULL) && ((cvs_sendarg(root, "-D", 0) < 0) ||
1.21 xsa 187: (cvs_sendarg(root, tag_date, 0) < 0)))
1.17 jfb 188: return (CVS_EX_PROTO);
1.1 jfb 189:
1.17 jfb 190: if (cvs_sendarg(root, tag_name, 0) < 0)
1.11 joris 191: return (CVS_EX_PROTO);
1.1 jfb 192: }
1.7 joris 193:
1.1 jfb 194: return (0);
195: }
196:
197:
198: /*
1.14 jfb 199: * cvs_tag_remote()
1.1 jfb 200: *
201: * Get the status of a single file.
202: */
1.14 jfb 203: static int
204: cvs_tag_remote(CVSFILE *cfp, void *arg)
1.1 jfb 205: {
1.14 jfb 206: int ret;
207: char fpath[MAXPATHLEN];
1.1 jfb 208: struct cvsroot *root;
209:
210: ret = 0;
211: root = CVS_DIR_ROOT(cfp);
212:
1.14 jfb 213: if (cfp->cf_type == DT_DIR) {
1.16 joris 214: if (cvs_senddir(root, cfp) < 0)
215: ret = CVS_EX_PROTO;
1.14 jfb 216: return (ret);
217: }
218:
219: if (cvs_sendentry(root, cfp) < 0) {
220: return (CVS_EX_PROTO);
1.1 jfb 221: }
222:
223: cvs_file_getpath(cfp, fpath, sizeof(fpath));
224:
1.14 jfb 225: switch (cfp->cf_cvstat) {
226: case CVS_FST_UNKNOWN:
227: ret = cvs_sendreq(root, CVS_REQ_QUESTIONABLE, cfp->cf_name);
228: break;
229: case CVS_FST_UPTODATE:
230: ret = cvs_sendreq(root, CVS_REQ_UNCHANGED, cfp->cf_name);
231: break;
232: case CVS_FST_MODIFIED:
1.22 joris 233: ret = cvs_sendreq(root, CVS_REQ_ISMODIFIED, cfp->cf_name);
1.14 jfb 234: default:
235: break;
236: }
237:
1.16 joris 238: if (ret == -1)
239: ret = CVS_EX_PROTO;
240:
1.14 jfb 241: return (ret);
242: }
243:
244:
245: static int
246: cvs_tag_local(CVSFILE *cf, void *arg)
247: {
1.25 xsa 248: char fpath[MAXPATHLEN], rcspath[MAXPATHLEN];
1.14 jfb 249: RCSFILE *rf;
250: RCSNUM *tag_rev;
251:
252: cvs_file_getpath(cf, fpath, sizeof(fpath));
253:
1.17 jfb 254: if (cf->cf_type == DT_DIR) {
1.23 xsa 255: if (verbosity > 1)
1.29 xsa 256: cvs_log(LP_NOTICE, "%s %s",
1.23 xsa 257: tag_delete ? "Untagging" : "Tagging", fpath);
1.17 jfb 258: return (CVS_EX_OK);
259: }
260:
1.14 jfb 261: if (cf->cf_cvstat == CVS_FST_UNKNOWN) {
1.26 xsa 262: if (verbosity > 1)
263: cvs_log(LP_WARN, "nothing known about %s", fpath);
1.14 jfb 264: return (0);
265: }
1.1 jfb 266:
1.17 jfb 267: tag_rev = cf->cf_lrev;
1.1 jfb 268:
1.25 xsa 269: if (cvs_rcs_getpath(cf, rcspath, sizeof(rcspath)) == NULL)
1.16 joris 270: return (CVS_EX_DATA);
1.1 jfb 271:
1.14 jfb 272: rf = rcs_open(rcspath, RCS_READ|RCS_WRITE);
273: if (rf == NULL) {
274: cvs_log(LP_ERR, "failed to open %s: %s", rcspath,
275: rcs_errstr(rcs_errno));
1.16 joris 276: return (CVS_EX_DATA);
1.32 ! xsa 277: }
! 278:
! 279: if (tag_delete == 1) {
! 280: /* XXX */
! 281: if (verbosity > 0)
! 282: cvs_printf("D %s\n", fpath);
! 283:
! 284: return (0);
1.14 jfb 285: }
1.1 jfb 286:
1.27 xsa 287: if (cvs_noexec == 0) {
1.18 xsa 288: if (rcs_sym_add(rf, tag_name, tag_rev) < 0) {
289: cvs_log(LP_ERR, "failed to tag %s: %s", rcspath,
290: rcs_errstr(rcs_errno));
291: }
1.1 jfb 292: }
1.17 jfb 293:
1.24 xsa 294: if (verbosity > 0)
295: cvs_printf("T %s\n", fpath);
1.1 jfb 296:
1.14 jfb 297: rcs_close(rf);
298: return (0);
1.1 jfb 299: }