1 //
2 // aegis - project change supervisor
3 // Copyright (C) 1991-1995, 1997-1999, 2001-2008, 2011, 2012 Peter Miller
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or (at
8 // your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 //
18
19 #include <common/ac/stdio.h>
20 #include <common/ac/stdlib.h>
21
22 #include <common/progname.h>
23 #include <common/quit.h>
24 #include <common/sizeof.h>
25 #include <common/str_list.h>
26 #include <common/trace.h>
27 #include <libaegis/ael/project/integrators.h>
28 #include <libaegis/arglex/project.h>
29 #include <libaegis/arglex2.h>
30 #include <libaegis/change/identifier.h>
31 #include <libaegis/commit.h>
32 #include <libaegis/help.h>
33 #include <libaegis/lock.h>
34 #include <libaegis/os.h>
35 #include <libaegis/project.h>
36 #include <libaegis/project/history.h>
37 #include <libaegis/sub.h>
38 #include <libaegis/user.h>
39
40 #include <aegis/aeri.h>
41
42
43 static void
remove_integrator_usage(void)44 remove_integrator_usage(void)
45 {
46 const char *progname;
47
48 progname = progname_get();
49 fprintf
50 (
51 stderr,
52 "usage: %s -Remove_Integrator [ <option>... ] <username>...\n",
53 progname
54 );
55 fprintf
56 (
57 stderr,
58 " %s -Remove_Integrator -List [ <option>... ]\n",
59 progname
60 );
61 fprintf(stderr, " %s -Remove_Integrator -Help\n", progname);
62 quit(1);
63 }
64
65
66 static void
remove_integrator_help(void)67 remove_integrator_help(void)
68 {
69 help("aeri", remove_integrator_usage);
70 }
71
72
73 static void
remove_integrator_list(void)74 remove_integrator_list(void)
75 {
76 trace(("remove_integrator_list()\n{\n"));
77 arglex();
78 change_identifier cid;
79 cid.command_line_parse_rest(remove_integrator_usage);
80 list_integrators(cid, 0);
81 trace(("}\n"));
82 }
83
84
85 static void
remove_integrator_inner(project * pp,string_list_ty * wlp,int strict)86 remove_integrator_inner(project *pp, string_list_ty *wlp, int strict)
87 {
88 size_t j;
89 user_ty::pointer up;
90
91 //
92 // locate user data
93 //
94 up = user_ty::create();
95
96 //
97 // lock the project for change
98 //
99 pp->pstate_lock_prepare();
100 lock_take();
101
102 //
103 // check they are allowed to do this
104 //
105 if (!project_administrator_query(pp, up->name()))
106 project_fatal(pp, 0, i18n("not an administrator"));
107
108 //
109 // check they they are OK users
110 //
111 for (j = 0; j < wlp->nstrings; ++j)
112 {
113 nstring name(wlp->string[j]);
114 if (!project_integrator_query(pp, name))
115 {
116 if (!strict)
117 continue;
118 sub_context_ty sc;
119 sc.var_set_string("Name", name);
120 project_fatal(pp, &sc, i18n("user \"$name\" is not an integrator"));
121 // NOTREACHED
122 }
123 project_integrator_remove(pp, name);
124 }
125
126 //
127 // write out and release lock
128 //
129 pp->pstate_write();
130 commit();
131 lock_release();
132
133 //
134 // verbose success message
135 //
136 for (j = 0; j < wlp->nstrings; ++j)
137 {
138 sub_context_ty *scp;
139
140 scp = sub_context_new();
141 sub_var_set_string(scp, "Name", wlp->string[j]);
142 project_verbose(pp, scp, i18n("remove integrator $name complete"));
143 sub_context_delete(scp);
144 }
145 }
146
147
148 static void
remove_integrator_main(void)149 remove_integrator_main(void)
150 {
151 string_ty *s1;
152 string_ty *project_name;
153 project *pp;
154 int recursive;
155
156 trace(("remove_integrator_main()\n{\n"));
157 arglex();
158 string_list_ty wl;
159 project_name = 0;
160 recursive = 0;
161 while (arglex_token != arglex_token_eoln)
162 {
163 switch (arglex_token)
164 {
165 default:
166 generic_argument(remove_integrator_usage);
167 continue;
168
169 case arglex_token_project_recursive:
170 recursive = 1;
171 break;
172
173 case arglex_token_user:
174 if (arglex() != arglex_token_string)
175 option_needs_name(arglex_token_user, remove_integrator_usage);
176 // fall through...
177
178 case arglex_token_string:
179 s1 = str_from_c(arglex_value.alv_string);
180 if (wl.member(s1))
181 {
182 sub_context_ty *scp;
183
184 scp = sub_context_new();
185 sub_var_set_string(scp, "Name", s1);
186 fatal_intl(scp, i18n("too many user $name"));
187 // NOTREACHED
188 sub_context_delete(scp);
189 }
190 wl.push_back(s1);
191 str_free(s1);
192 break;
193
194 case arglex_token_project:
195 arglex();
196 arglex_parse_project(&project_name, remove_integrator_usage);
197 continue;
198
199 case arglex_token_wait:
200 case arglex_token_wait_not:
201 user_ty::lock_wait_argument(remove_integrator_usage);
202 break;
203 }
204 arglex();
205 }
206 if (!wl.nstrings)
207 {
208 error_intl(0, i18n("no user names"));
209 remove_integrator_usage();
210 }
211
212 //
213 // locate project data
214 //
215 if (!project_name)
216 {
217 nstring n = user_ty::create()->default_project();
218 project_name = str_copy(n.get_ref());
219 }
220 pp = project_alloc(project_name);
221 str_free(project_name);
222 pp->bind_existing();
223
224 if (recursive)
225 {
226 string_list_ty pl;
227 pp->list_inner(pl);
228 for (size_t j = 0; j < pl.nstrings; ++j)
229 {
230 project *branch;
231 branch = project_alloc(pl.string[j]);
232 branch->bind_existing();
233 remove_integrator_inner(branch, &wl, 0);
234 project_free(branch);
235 }
236 }
237 else
238 {
239 remove_integrator_inner(pp, &wl, 1);
240 }
241 project_free(pp);
242 trace(("}\n"));
243 }
244
245
246 void
remove_integrator(void)247 remove_integrator(void)
248 {
249 static arglex_dispatch_ty dispatch[] =
250 {
251 { arglex_token_help, remove_integrator_help, 0 },
252 { arglex_token_list, remove_integrator_list, 0 },
253 };
254
255 trace(("remove_integrator()\n{\n"));
256 arglex_dispatch(dispatch, SIZEOF(dispatch), remove_integrator_main);
257 trace(("}\n"));
258 }
259
260
261 // vim: set ts=8 sw=4 et :
262