Annotation of src/usr.bin/cvs/tag.c, Revision 1.26
1.26 ! xsa 1: /* $OpenBSD: tag.c,v 1.25 2005/07/14 06:50:50 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.17 jfb 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",
73: { },
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.14 jfb 146: if (tag_branch && tag_delete) {
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.14 jfb 151: if (tag_delete && tag_oldname)
152: tag_oldname = NULL;
1.1 jfb 153:
1.14 jfb 154: if (tag_delete && tag_date)
155: tag_date = NULL;
1.3 jfb 156:
1.14 jfb 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) {
169: if (tag_branch && (cvs_sendarg(root, "-b", 0) < 0))
170: return (CVS_EX_PROTO);
171:
172: if (tag_delete && (cvs_sendarg(root, "-d", 0) < 0))
173: return (CVS_EX_PROTO);
1.7 joris 174:
1.21 xsa 175: if (tag_forcemove && (cvs_sendarg(root, "-F", 0) < 0))
176: return (CVS_EX_PROTO);
177:
178: if (tag_forcehead && (cvs_sendarg(root, "-f", 0) < 0))
179: return (CVS_EX_PROTO);
180:
181: if ((tag_oldname) && ((cvs_sendarg(root, "-r", 0) < 0) ||
182: (cvs_sendarg(root, tag_oldname, 0) < 0)))
1.17 jfb 183: return (CVS_EX_PROTO);
1.1 jfb 184:
1.21 xsa 185: if ((tag_date) && ((cvs_sendarg(root, "-D", 0) < 0) ||
186: (cvs_sendarg(root, tag_date, 0) < 0)))
1.17 jfb 187: return (CVS_EX_PROTO);
1.1 jfb 188:
1.17 jfb 189: if (cvs_sendarg(root, tag_name, 0) < 0)
1.11 joris 190: return (CVS_EX_PROTO);
1.1 jfb 191: }
1.7 joris 192:
1.1 jfb 193: return (0);
194: }
195:
196:
197: /*
1.14 jfb 198: * cvs_tag_remote()
1.1 jfb 199: *
200: * Get the status of a single file.
201: */
1.14 jfb 202: static int
203: cvs_tag_remote(CVSFILE *cfp, void *arg)
1.1 jfb 204: {
1.14 jfb 205: int ret;
206: char fpath[MAXPATHLEN];
1.1 jfb 207: struct cvsroot *root;
208:
209: ret = 0;
210: root = CVS_DIR_ROOT(cfp);
211:
1.14 jfb 212: if (cfp->cf_type == DT_DIR) {
1.16 joris 213: if (cvs_senddir(root, cfp) < 0)
214: ret = CVS_EX_PROTO;
1.14 jfb 215: return (ret);
216: }
217:
218: if (cvs_sendentry(root, cfp) < 0) {
219: return (CVS_EX_PROTO);
1.1 jfb 220: }
221:
222: cvs_file_getpath(cfp, fpath, sizeof(fpath));
223:
1.14 jfb 224: switch (cfp->cf_cvstat) {
225: case CVS_FST_UNKNOWN:
226: ret = cvs_sendreq(root, CVS_REQ_QUESTIONABLE, cfp->cf_name);
227: break;
228: case CVS_FST_UPTODATE:
229: ret = cvs_sendreq(root, CVS_REQ_UNCHANGED, cfp->cf_name);
230: break;
231: case CVS_FST_MODIFIED:
1.22 joris 232: ret = cvs_sendreq(root, CVS_REQ_ISMODIFIED, cfp->cf_name);
1.14 jfb 233: default:
234: break;
235: }
236:
1.16 joris 237: if (ret == -1)
238: ret = CVS_EX_PROTO;
239:
1.14 jfb 240: return (ret);
241: }
242:
243:
244: static int
245: cvs_tag_local(CVSFILE *cf, void *arg)
246: {
1.25 xsa 247: char fpath[MAXPATHLEN], rcspath[MAXPATHLEN];
1.14 jfb 248: RCSFILE *rf;
249: RCSNUM *tag_rev;
250:
251: cvs_file_getpath(cf, fpath, sizeof(fpath));
252:
1.17 jfb 253: if (cf->cf_type == DT_DIR) {
1.23 xsa 254: if (verbosity > 1)
255: cvs_log(LP_INFO, "%s %s",
256: tag_delete ? "Untagging" : "Tagging", fpath);
1.17 jfb 257: return (CVS_EX_OK);
258: }
259:
1.14 jfb 260: if (cf->cf_cvstat == CVS_FST_UNKNOWN) {
1.26 ! xsa 261: if (verbosity > 1)
! 262: cvs_log(LP_WARN, "nothing known about %s", fpath);
1.14 jfb 263: return (0);
264: }
1.1 jfb 265:
1.17 jfb 266: tag_rev = cf->cf_lrev;
1.1 jfb 267:
1.25 xsa 268: if (cvs_rcs_getpath(cf, rcspath, sizeof(rcspath)) == NULL)
1.16 joris 269: return (CVS_EX_DATA);
1.1 jfb 270:
1.14 jfb 271: rf = rcs_open(rcspath, RCS_READ|RCS_WRITE);
272: if (rf == NULL) {
273: cvs_log(LP_ERR, "failed to open %s: %s", rcspath,
274: rcs_errstr(rcs_errno));
1.16 joris 275: return (CVS_EX_DATA);
1.14 jfb 276: }
1.1 jfb 277:
1.18 xsa 278: if (!cvs_noexec) {
279: if (rcs_sym_add(rf, tag_name, tag_rev) < 0) {
280: cvs_log(LP_ERR, "failed to tag %s: %s", rcspath,
281: rcs_errstr(rcs_errno));
282: }
1.1 jfb 283: }
1.17 jfb 284:
1.24 xsa 285: if (verbosity > 0)
286: cvs_printf("T %s\n", fpath);
1.1 jfb 287:
1.14 jfb 288: rcs_close(rf);
289: return (0);
1.1 jfb 290: }