release.c revision 1.39
1/*	$OpenBSD: release.c,v 1.39 2008/02/23 13:07:43 xsa Exp $	*/
2/*-
3 * Copyright (c) 2005-2007 Xavier Santolaria <xsa@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <sys/stat.h>
19
20#include <string.h>
21#include <unistd.h>
22
23#include "cvs.h"
24#include "remote.h"
25
26void	cvs_release_local(struct cvs_file *);
27
28static void	release_check_files(struct cvs_file *);
29
30static int	dflag = 0;
31static int	files_altered = 0;
32
33struct cvs_cmd cvs_cmd_release = {
34	CVS_OP_RELEASE, CVS_USE_WDIR, "release",
35	{ "re", "rel" },
36	"Indicate that a Module is no longer in use",
37	"[-d] dir...",
38	"d",
39	NULL,
40	cvs_release
41};
42
43int
44cvs_release(int argc, char **argv)
45{
46	int ch;
47	int flags;
48	struct cvs_recursion cr;
49
50	flags = CR_REPO;
51
52	while ((ch = getopt(argc, argv, cvs_cmd_release.cmd_opts)) != -1) {
53		switch (ch) {
54		case 'd':
55			dflag = 1;
56			break;
57		default:
58			fatal("%s", cvs_cmd_release.cmd_synopsis);
59		}
60	}
61
62	argc -= optind;
63	argv += optind;
64
65	if (argc == 0)
66		fatal("%s", cvs_cmd_release.cmd_synopsis);
67
68	cr.enterdir = NULL;
69	cr.leavedir = NULL;
70
71	if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
72		cvs_client_connect_to_server();
73		cr.fileproc = cvs_client_sendfile;
74
75		if (dflag == 1)
76			cvs_client_send_request("Argument -d");
77	} else
78		cr.fileproc = cvs_release_local;
79
80	cr.flags = flags;
81
82	cvs_file_run(argc, argv, &cr);
83
84	if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) {
85		cvs_client_send_files(argv, argc);
86		cvs_client_senddir(".");
87		cvs_client_send_request("release");
88		cvs_client_get_responses();
89	}
90
91	return (0);
92}
93
94void
95cvs_release_local(struct cvs_file *cf)
96{
97	struct stat st;
98	struct cvs_recursion cr;
99	char *wdir, cwd[MAXPATHLEN];
100	char *arg = ".";
101	int saved_noexec;
102
103	if (cf->file_type == CVS_FILE)
104		return;
105
106	cvs_log(LP_TRACE, "cvs_release_local(%s)", cf->file_path);
107
108	cvs_file_classify(cf, cvs_directory_tag);
109
110	if (cvs_server_active == 1) {
111		cvs_history_add(CVS_HISTORY_RELEASE, cf, NULL);
112		return;
113	}
114
115	if ((wdir = getcwd(cwd, sizeof(cwd))) == NULL)
116		fatal("getcwd failed");
117
118	if (cf->file_type == CVS_DIR) {
119		if (!strcmp(cf->file_name, "."))
120			return;
121
122		/* chdir before updating the directory. */
123		cvs_chdir(cf->file_path, 0);
124
125		if (stat(CVS_PATH_CVSDIR, &st) == -1 || !S_ISDIR(st.st_mode)) {
126			cvs_log(LP_ERR, "no repository directory: %s",
127			    cf->file_path);
128			return;
129		}
130	}
131
132	/* Skip the interactive part if -Q is specified. */
133	if (verbosity == 0)
134		goto delete;
135
136	saved_noexec = cvs_noexec;
137	cvs_noexec = 1;
138
139	cr.enterdir = NULL;
140	cr.leavedir = NULL;
141	cr.fileproc = cvs_update_local;
142	cr.flags = CR_REPO | CR_RECURSE_DIRS;
143
144	cvs_file_run(1, &arg, &cr);
145
146	cvs_noexec = saved_noexec;
147
148	cr.enterdir = NULL;
149	cr.leavedir = NULL;
150	cr.fileproc = release_check_files;
151	cr.flags = CR_RECURSE_DIRS;
152
153	cvs_file_run(1, &arg, &cr);
154
155	(void)printf("You have [%d] altered files in this repository.\n",
156	    files_altered);
157	(void)printf("Are you sure you want to release %sdirectory `%s': ",
158		(dflag == 1) ? "(and delete) " : "", cf->file_path);
159
160	if (cvs_yesno() == -1) {
161		(void)fprintf(stderr,
162		    "** `%s' aborted by user choice.\n", cmdp->cmd_name);
163
164		/* change back to original working dir */
165		cvs_chdir(wdir, 0);
166
167		return;
168	}
169
170	/* change back to original working dir */
171	cvs_chdir(wdir, 0);
172
173delete:
174	if (dflag == 1) {
175		if (cvs_rmdir(cf->file_path) != 0)
176			fatal("cvs_release_local: cvs_rmdir failed");
177	}
178}
179
180static void
181release_check_files(struct cvs_file *cf)
182{
183	cvs_log(LP_TRACE, "release_check_files(%s)", cf->file_path);
184
185	cvs_file_classify(cf, cvs_directory_tag);
186
187	if (cf->file_status == FILE_MERGE ||
188	    cf->file_status == FILE_ADDED ||
189	    cf->file_status == FILE_PATCH ||
190	    cf->file_status == FILE_CONFLICT)
191		files_altered++;
192	return;
193}
194