xref: /openbsd-src/usr.bin/cvs/commit.c (revision c710bc5ac3ac106f5516424806920d4eebc6fe09)
1 /*	$OpenBSD: commit.c,v 1.6 2004/11/26 16:23:50 jfb Exp $	*/
2 /*
3  * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. The name of the author may not be used to endorse or promote products
13  *    derived from this software without specific prior written permission.
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
24  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include <sys/types.h>
28 #include <sys/queue.h>
29 #include <sys/stat.h>
30 
31 #include <errno.h>
32 #include <stdio.h>
33 #include <fcntl.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <string.h>
37 #include <sysexits.h>
38 
39 #include "cvs.h"
40 #include "log.h"
41 #include "buf.h"
42 #include "proto.h"
43 
44 
45 LIST_HEAD(ci_list, ci_file);
46 
47 struct ci_file {
48 	char   *ci_path;
49 	RCSNUM *ci_rev;
50 	LIST_ENTRY(ci_file) ci_link;
51 };
52 
53 
54 
55 int    cvs_commit_file     (CVSFILE *, void *);
56 
57 
58 /*
59  * cvs_commit()
60  *
61  * Handler for the `cvs commit' command.
62  */
63 
64 int
65 cvs_commit(int argc, char **argv)
66 {
67 	int ch, recurse, flags;
68 	char *msg, *mfile;
69 	struct ci_list cl;
70 
71 	flags = 0;
72 	recurse = 1;
73 	mfile = NULL;
74 	msg = NULL;
75 	LIST_INIT(&cl);
76 
77 	while ((ch = getopt(argc, argv, "F:flm:R")) != -1) {
78 		switch (ch) {
79 		case 'F':
80 			mfile = optarg;
81 			break;
82 		case 'f':
83 			recurse = 0;
84 			break;
85 		case 'l':
86 			recurse = 0;
87 			break;
88 		case 'm':
89 			msg = optarg;
90 			break;
91 		case 'R':
92 			recurse = 1;
93 			break;
94 		default:
95 			return (EX_USAGE);
96 		}
97 	}
98 
99 	if ((msg != NULL) && (mfile != NULL)) {
100 		cvs_log(LP_ERR, "the -F and -m flags are mutually exclusive");
101 		return (EX_USAGE);
102 	}
103 
104 	if ((mfile != NULL) && (msg = cvs_logmsg_open(mfile)) == NULL)
105 		return (EX_DATAERR);
106 
107 	argc -= optind;
108 	argv += optind;
109 
110 	if (argc == 0)
111 		cvs_files = cvs_file_get(".", flags);
112 	else {
113 		cvs_files = cvs_file_getspec(argv, argc, flags);
114 	}
115 	if (cvs_files == NULL)
116 		return (EX_DATAERR);
117 
118 	cvs_file_examine(cvs_files, cvs_commit_file, &cl);
119 
120 	cvs_senddir(cvs_files->cf_ddat->cd_root, cvs_files);
121 	cvs_sendreq(cvs_files->cf_ddat->cd_root, CVS_REQ_CI, NULL);
122 
123 	return (0);
124 }
125 
126 
127 /*
128  * cvs_commit_file()
129  *
130  * Commit a single file.
131  */
132 
133 int
134 cvs_commit_file(CVSFILE *cf, void *arg)
135 {
136 	char *repo, rcspath[MAXPATHLEN], fpath[MAXPATHLEN];
137 	RCSFILE *rf;
138 	struct cvsroot *root;
139 	struct cvs_ent *entp;
140 	struct ci_list *cl;
141 
142 	cl = (struct ci_list *)arg;
143 
144 	if (cf->cf_type == DT_DIR) {
145 		if (cf->cf_cvstat != CVS_FST_UNKNOWN) {
146 			root = cf->cf_ddat->cd_root;
147 			if ((cf->cf_parent == NULL) ||
148 			    (root != cf->cf_parent->cf_ddat->cd_root)) {
149 				cvs_connect(root);
150 			}
151 
152 			cvs_senddir(root, cf);
153 		}
154 
155 		return (0);
156 	}
157 	else
158 		root = cf->cf_parent->cf_ddat->cd_root;
159 
160 	rf = NULL;
161 	if (cf->cf_parent != NULL) {
162 		repo = cf->cf_parent->cf_ddat->cd_repo;
163 	}
164 	else {
165 		repo = NULL;
166 	}
167 
168 	entp = cvs_ent_getent(fpath);
169 	if (entp == NULL)
170 		return (-1);
171 
172 	if ((cf->cf_cvstat == CVS_FST_ADDED) ||
173 	    (cf->cf_cvstat == CVS_FST_MODIFIED)) {
174 		if ((root->cr_method != CVS_METHOD_LOCAL) &&
175 		    (cvs_sendentry(root, entp) < 0)) {
176 			cvs_ent_free(entp);
177 			return (-1);
178 		}
179 
180 		cvs_sendreq(root, CVS_REQ_MODIFIED, CVS_FILE_NAME(cf));
181 		cvs_sendfile(root, fpath);
182 	}
183 
184 	snprintf(rcspath, sizeof(rcspath), "%s/%s/%s%s",
185 	    root->cr_dir, repo, fpath, RCS_FILE_EXT);
186 
187 	cvs_ent_free(entp);
188 
189 	return (0);
190 }
191