Annotation of src/usr.bin/cvs/tag.c, Revision 1.39
1.39 ! xsa 1: /* $OpenBSD: tag.c,v 1.38 2006/01/27 15:42:35 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:
1.38 xsa 134: if (!rcs_sym_check(tag_name))
135: fatal("tag `%s' must not contain the characters `%s'",
1.15 jfb 136: tag_name, RCS_SYM_INVALCHAR);
1.1 jfb 137:
1.31 xsa 138: if ((tag_branch == 1) && (tag_delete == 1)) {
1.1 jfb 139: cvs_log(LP_WARN, "ignoring -b with -d options");
1.14 jfb 140: tag_branch = 0;
1.1 jfb 141: }
142:
1.31 xsa 143: if ((tag_delete == 1) && (tag_oldname != NULL))
1.14 jfb 144: tag_oldname = NULL;
1.1 jfb 145:
1.31 xsa 146: if ((tag_delete == 1) && (tag_date != NULL))
1.14 jfb 147: tag_date = NULL;
1.3 jfb 148:
1.31 xsa 149: if ((tag_oldname != NULL) && (tag_date != NULL)) {
1.20 xsa 150: cvs_log(LP_ERR, "the -D and -r options are mutually exclusive");
1.11 joris 151: return (CVS_EX_USAGE);
1.3 jfb 152: }
153:
1.7 joris 154: return (0);
155: }
156:
1.14 jfb 157: static int
1.17 jfb 158: cvs_tag_pre_exec(struct cvsroot *root)
1.7 joris 159: {
1.17 jfb 160: if (root->cr_method != CVS_METHOD_LOCAL) {
1.35 joris 161: if (tag_branch == 1)
162: cvs_sendarg(root, "-b", 0);
1.17 jfb 163:
1.35 joris 164: if (tag_delete == 1)
165: cvs_sendarg(root, "-d", 0);
1.7 joris 166:
1.35 joris 167: if (tag_forcemove == 1)
168: cvs_sendarg(root, "-F", 0);
1.21 xsa 169:
1.35 joris 170: if (tag_forcehead == 1)
171: cvs_sendarg(root, "-f", 0);
1.21 xsa 172:
1.35 joris 173: if (tag_oldname != NULL) {
174: cvs_sendarg(root, "-r", 0);
175: cvs_sendarg(root, tag_oldname, 0);
176: }
1.1 jfb 177:
1.35 joris 178: if (tag_date != NULL) {
179: cvs_sendarg(root, "-D", 0);
180: cvs_sendarg(root, tag_date, 0);
181: }
1.1 jfb 182:
1.35 joris 183: cvs_sendarg(root, tag_name, 0);
1.1 jfb 184: }
1.7 joris 185:
1.1 jfb 186: return (0);
187: }
188:
189:
190: /*
1.14 jfb 191: * cvs_tag_remote()
1.1 jfb 192: *
193: * Get the status of a single file.
194: */
1.14 jfb 195: static int
196: cvs_tag_remote(CVSFILE *cfp, void *arg)
1.1 jfb 197: {
1.14 jfb 198: char fpath[MAXPATHLEN];
1.1 jfb 199: struct cvsroot *root;
200:
201: root = CVS_DIR_ROOT(cfp);
202:
1.14 jfb 203: if (cfp->cf_type == DT_DIR) {
1.35 joris 204: cvs_senddir(root, cfp);
205: return (0);
1.1 jfb 206: }
207:
1.35 joris 208: cvs_sendentry(root, cfp);
1.1 jfb 209: cvs_file_getpath(cfp, fpath, sizeof(fpath));
210:
1.14 jfb 211: switch (cfp->cf_cvstat) {
212: case CVS_FST_UNKNOWN:
1.35 joris 213: cvs_sendreq(root, CVS_REQ_QUESTIONABLE, cfp->cf_name);
1.14 jfb 214: break;
215: case CVS_FST_UPTODATE:
1.35 joris 216: cvs_sendreq(root, CVS_REQ_UNCHANGED, cfp->cf_name);
1.14 jfb 217: break;
218: case CVS_FST_MODIFIED:
1.35 joris 219: cvs_sendreq(root, CVS_REQ_ISMODIFIED, cfp->cf_name);
1.14 jfb 220: default:
221: break;
222: }
223:
1.35 joris 224: return (0);
1.14 jfb 225: }
226:
227:
228: static int
229: cvs_tag_local(CVSFILE *cf, void *arg)
230: {
1.39 ! xsa 231: char fpath[MAXPATHLEN], numbuf[64], rcspath[MAXPATHLEN];
1.14 jfb 232: RCSFILE *rf;
233: RCSNUM *tag_rev;
234:
235: cvs_file_getpath(cf, fpath, sizeof(fpath));
236:
1.17 jfb 237: if (cf->cf_type == DT_DIR) {
1.23 xsa 238: if (verbosity > 1)
1.29 xsa 239: cvs_log(LP_NOTICE, "%s %s",
1.23 xsa 240: tag_delete ? "Untagging" : "Tagging", fpath);
1.17 jfb 241: return (CVS_EX_OK);
242: }
243:
1.14 jfb 244: if (cf->cf_cvstat == CVS_FST_UNKNOWN) {
1.26 xsa 245: if (verbosity > 1)
246: cvs_log(LP_WARN, "nothing known about %s", fpath);
1.33 xsa 247: return (0);
248: } else if (cf->cf_cvstat == CVS_FST_ADDED) {
249: if (verbosity > 1)
250: cvs_log(LP_WARN,
251: "couldn't tag added but un-commited file `%s'",
252: fpath);
253: return (0);
254: } else if (cf->cf_cvstat == CVS_FST_REMOVED) {
255: if (verbosity > 1)
256: cvs_log(LP_WARN,
257: "skipping removed but un-commited file `%s'",
258: fpath);
1.14 jfb 259: return (0);
260: }
1.1 jfb 261:
1.17 jfb 262: tag_rev = cf->cf_lrev;
1.1 jfb 263:
1.34 xsa 264: cvs_rcs_getpath(cf, rcspath, sizeof(rcspath));
1.1 jfb 265:
1.37 xsa 266: if ((rf = rcs_open(rcspath, RCS_READ|RCS_WRITE)) == NULL)
267: fatal("cvs_tag_local: rcs_open: %s: %s", rcspath,
1.14 jfb 268: rcs_errstr(rcs_errno));
1.32 xsa 269:
270: if (tag_delete == 1) {
1.39 ! xsa 271: if (cvs_noexec == 0) {
! 272: if (rcs_sym_remove(rf, tag_name) < 0)
! 273: fatal("failed to remove tag %s from %s",
! 274: tag_name, rcspath);
! 275: }
! 276:
1.32 xsa 277: if (verbosity > 0)
278: cvs_printf("D %s\n", fpath);
279:
1.39 ! xsa 280: rcs_close(rf);
1.32 xsa 281: return (0);
1.14 jfb 282: }
1.1 jfb 283:
1.27 xsa 284: if (cvs_noexec == 0) {
1.39 ! xsa 285: if (rcs_sym_add(rf, tag_name, tag_rev) < 0) {
! 286: rcsnum_tostr(tag_rev, numbuf, sizeof(numbuf));
! 287: fatal("failed to set tag %s to revision %s in %s",
! 288: tag_name, numbuf, rcspath);
! 289: }
1.1 jfb 290: }
1.17 jfb 291:
1.24 xsa 292: if (verbosity > 0)
293: cvs_printf("T %s\n", fpath);
1.1 jfb 294:
1.14 jfb 295: rcs_close(rf);
296: return (0);
1.1 jfb 297: }