Annotation of src/usr.bin/cvs/commit.c, Revision 1.53
1.53 ! joris 1: /* $OpenBSD: commit.c,v 1.52 2006/03/16 09:06:19 xsa Exp $ */
1.1 jfb 2: /*
3: * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
1.9 tedu 4: * All rights reserved.
1.1 jfb 5: *
1.9 tedu 6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
1.1 jfb 9: *
1.9 tedu 10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
1.1 jfb 12: * 2. The name of the author may not be used to endorse or promote products
1.9 tedu 13: * derived from this software without specific prior written permission.
1.1 jfb 14: *
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
16: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
17: * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
18: * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
1.9 tedu 24: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.1 jfb 25: */
26:
1.51 xsa 27: #include "includes.h"
1.1 jfb 28:
1.37 xsa 29: #include "buf.h"
1.1 jfb 30: #include "cvs.h"
31: #include "log.h"
1.2 jfb 32: #include "proto.h"
1.1 jfb 33:
34:
1.45 xsa 35: static int cvs_commit_init(struct cvs_cmd *, int, char **, int *);
36: static int cvs_commit_prepare(CVSFILE *, void *);
37: static int cvs_commit_remote(CVSFILE *, void *);
38: static int cvs_commit_local(CVSFILE *, void *);
39: static int cvs_commit_pre_exec(struct cvsroot *);
1.34 jfb 40:
41: struct cvs_cmd cvs_cmd_commit = {
42: CVS_OP_COMMIT, CVS_REQ_CI, "commit",
43: { "ci", "com" },
44: "Check files into the repository",
45: "[-flR] [-F logfile | -m msg] [-r rev] ...",
46: "F:flm:Rr:",
1.18 joris 47: NULL,
1.34 jfb 48: CF_RECURSE | CF_IGNORE | CF_SORT,
49: cvs_commit_init,
50: cvs_commit_pre_exec,
1.39 xsa 51: cvs_commit_remote,
52: cvs_commit_local,
1.34 jfb 53: NULL,
54: NULL,
1.41 joris 55: CVS_CMD_SENDDIR | CVS_CMD_ALLOWSPEC | CVS_CMD_SENDARGS2
1.18 joris 56: };
1.1 jfb 57:
1.18 joris 58: static char *mfile = NULL;
1.35 xsa 59: static char *rev = NULL;
1.32 joris 60: static char **commit_files = NULL;
61: static int commit_fcount = 0;
1.43 joris 62: static int wantedstatus = 0;
1.6 jfb 63:
1.34 jfb 64: static int
65: cvs_commit_init(struct cvs_cmd *cmd, int argc, char **argv, int *arg)
1.1 jfb 66: {
1.18 joris 67: int ch;
1.3 krapht 68:
1.34 jfb 69: while ((ch = getopt(argc, argv, cmd->cmd_opts)) != -1) {
1.1 jfb 70: switch (ch) {
71: case 'F':
72: mfile = optarg;
73: break;
74: case 'f':
1.10 jfb 75: /* XXX half-implemented */
1.34 jfb 76: cmd->file_flags &= ~CF_RECURSE;
1.1 jfb 77: break;
78: case 'l':
1.34 jfb 79: cmd->file_flags &= ~CF_RECURSE;
1.1 jfb 80: break;
81: case 'm':
1.47 joris 82: cvs_msg = xstrdup(optarg);
1.1 jfb 83: break;
84: case 'R':
1.34 jfb 85: cmd->file_flags |= CF_RECURSE;
1.1 jfb 86: break;
1.35 xsa 87: case 'r':
88: rev = optarg;
89: break;
1.1 jfb 90: default:
1.23 joris 91: return (CVS_EX_USAGE);
1.1 jfb 92: }
93: }
94:
1.14 jfb 95: if ((cvs_msg != NULL) && (mfile != NULL)) {
1.1 jfb 96: cvs_log(LP_ERR, "the -F and -m flags are mutually exclusive");
1.23 joris 97: return (CVS_EX_USAGE);
1.1 jfb 98: }
99:
1.48 xsa 100: if (mfile != NULL)
101: cvs_msg = cvs_logmsg_open(mfile);
1.1 jfb 102:
1.18 joris 103: *arg = optind;
1.32 joris 104:
105: commit_files = (argv + optind);
106: commit_fcount = (argc - optind);
107:
1.18 joris 108: return (0);
109: }
1.1 jfb 110:
1.18 joris 111: int
1.34 jfb 112: cvs_commit_pre_exec(struct cvsroot *root)
1.18 joris 113: {
114: CVSFILE *cfp;
1.32 joris 115: CVSFILE *tmp;
1.44 joris 116: int ret, i, flags = CF_RECURSE | CF_IGNORE | CF_SORT;
1.43 joris 117: struct cvs_flist added, modified, removed, *cl[3];
118: int stattype[] = { CVS_FST_ADDED, CVS_FST_MODIFIED, CVS_FST_REMOVED };
119:
120: SIMPLEQ_INIT(&added);
121: SIMPLEQ_INIT(&modified);
122: SIMPLEQ_INIT(&removed);
123:
124: cl[0] = &added;
125: cl[1] = &modified;
126: cl[2] = &removed;
127:
1.44 joris 128: if ((tmp = cvs_file_loadinfo(".", CF_NOFILES, NULL, NULL, 1)) == NULL)
129: return (CVS_EX_DATA);
130:
1.43 joris 131: /*
132: * Obtain the file lists for the logmessage.
133: */
134: for (i = 0; i < 3; i++) {
135: wantedstatus = stattype[i];
136: if (commit_fcount != 0) {
1.44 joris 137: ret = cvs_file_getspec(commit_files, commit_fcount,
138: flags, cvs_commit_prepare, cl[i], NULL);
1.43 joris 139: } else {
1.44 joris 140: ret = cvs_file_get(".", flags, cvs_commit_prepare,
141: cl[i], NULL);
1.43 joris 142: }
1.32 joris 143:
1.44 joris 144: if (ret != CVS_EX_OK) {
145: cvs_file_free(tmp);
1.43 joris 146: return (CVS_EX_DATA);
1.44 joris 147: }
1.32 joris 148: }
1.1 jfb 149:
1.43 joris 150: /*
151: * If we didn't catch any file, don't call the editor.
152: */
153: if (SIMPLEQ_EMPTY(&added) && SIMPLEQ_EMPTY(&modified) &&
154: SIMPLEQ_EMPTY(&removed)) {
1.32 joris 155: cvs_file_free(tmp);
1.11 jfb 156: return (0);
1.32 joris 157: }
1.7 jfb 158:
1.43 joris 159: /*
160: * Fetch the log message for real, with all the files.
161: */
1.17 joris 162: if (cvs_msg == NULL)
1.43 joris 163: cvs_msg = cvs_logmsg_get(tmp->cf_name, &added, &modified,
164: &removed);
1.32 joris 165:
166: cvs_file_free(tmp);
1.17 joris 167:
1.43 joris 168: /* free the file lists */
169: for (i = 0; i < 3; i++) {
170: while (!SIMPLEQ_EMPTY(cl[i])) {
171: cfp = SIMPLEQ_FIRST(cl[i]);
172: SIMPLEQ_REMOVE_HEAD(cl[i], cf_list);
173: cvs_file_free(cfp);
174: }
1.7 jfb 175: }
1.17 joris 176:
177: if (cvs_msg == NULL)
1.23 joris 178: return (CVS_EX_DATA);
1.35 xsa 179:
180: if (root->cr_method != CVS_METHOD_LOCAL) {
1.50 joris 181: cvs_logmsg_send(root, cvs_msg);
1.36 joris 182:
1.35 xsa 183: if (rev != NULL) {
1.50 joris 184: cvs_sendarg(root, "-r", 0);
185: cvs_sendarg(root, rev, 0);
1.35 xsa 186: }
187: }
1.7 jfb 188:
189: return (0);
190: }
191:
192: /*
193: * cvs_commit_prepare()
194: *
195: * Examine the file <cf> to see if it will be part of the commit, in which
196: * case it gets added to the list passed as second argument.
197: */
198: int
199: cvs_commit_prepare(CVSFILE *cf, void *arg)
200: {
201: CVSFILE *copy;
202: struct cvs_flist *clp = (struct cvs_flist *)arg;
203:
1.43 joris 204: if ((cf->cf_type == DT_REG) && (cf->cf_cvstat == wantedstatus)) {
1.7 jfb 205: copy = cvs_file_copy(cf);
206: if (copy == NULL)
1.23 joris 207: return (CVS_EX_DATA);
1.7 jfb 208:
1.26 jfb 209: SIMPLEQ_INSERT_TAIL(clp, copy, cf_list);
1.7 jfb 210: }
1.3 krapht 211:
1.6 jfb 212: return (0);
1.3 krapht 213: }
214:
215:
216: /*
1.39 xsa 217: * cvs_commit_remote()
1.3 krapht 218: *
1.6 jfb 219: * Commit a single file.
1.3 krapht 220: */
1.6 jfb 221: int
1.39 xsa 222: cvs_commit_remote(CVSFILE *cf, void *arg)
1.3 krapht 223: {
1.53 ! joris 224: char fpath[MAXPATHLEN];
1.6 jfb 225: struct cvsroot *root;
226:
1.12 jfb 227: root = CVS_DIR_ROOT(cf);
1.6 jfb 228:
229: if (cf->cf_type == DT_DIR) {
1.50 joris 230: if (cf->cf_cvstat != CVS_FST_UNKNOWN)
231: cvs_senddir(root, cf);
1.33 joris 232: return (0);
1.3 krapht 233: }
234:
1.7 jfb 235: cvs_file_getpath(cf, fpath, sizeof(fpath));
1.3 krapht 236:
1.6 jfb 237: if ((cf->cf_cvstat == CVS_FST_ADDED) ||
1.29 jfb 238: (cf->cf_cvstat == CVS_FST_MODIFIED) ||
239: (cf->cf_cvstat == CVS_FST_REMOVED)) {
1.50 joris 240: cvs_sendentry(root, cf);
1.31 joris 241:
1.39 xsa 242: /* if it's removed, don't bother sending a
243: * Modified request together with the file its
244: * contents.
245: */
246: if (cf->cf_cvstat == CVS_FST_REMOVED)
247: return (0);
1.16 joris 248:
1.50 joris 249: cvs_sendreq(root, CVS_REQ_MODIFIED, cf->cf_name);
250: cvs_sendfile(root, fpath);
1.5 krapht 251: }
1.3 krapht 252:
1.39 xsa 253: return (0);
254: }
255:
256: static int
257: cvs_commit_local(CVSFILE *cf, void *arg)
258: {
259: char fpath[MAXPATHLEN], rcspath[MAXPATHLEN];
260:
261: if (cf->cf_type == DT_DIR) {
262: if (verbosity > 1)
1.46 xsa 263: cvs_log(LP_NOTICE, "Examining %s", cf->cf_name);
1.39 xsa 264: return (0);
265: }
266:
267: cvs_file_getpath(cf, fpath, sizeof(fpath));
1.49 xsa 268: cvs_rcs_getpath(cf, rcspath, sizeof(rcspath));
1.3 krapht 269:
1.6 jfb 270: return (0);
1.1 jfb 271: }