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