1 //
2 // aegis - project change supervisor
3 // Copyright (C) 1994-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/assert.h>
20 #include <common/ac/stdio.h>
21
22 #include <common/gettime.h>
23 #include <common/progname.h>
24 #include <common/quit.h>
25 #include <common/sizeof.h>
26 #include <common/trace.h>
27 #include <libaegis/ael/project/history.h>
28 #include <libaegis/arglex2.h>
29 #include <libaegis/arglex/change.h>
30 #include <libaegis/arglex/project.h>
31 #include <libaegis/change/file.h>
32 #include <libaegis/change/identifier.h>
33 #include <libaegis/commit.h>
34 #include <libaegis/file/event.h>
35 #include <libaegis/help.h>
36 #include <libaegis/lock.h>
37 #include <libaegis/pconf.fmtgen.h>
38 #include <libaegis/project/file.h>
39 #include <libaegis/project/file/roll_forward.h>
40 #include <libaegis/project.h>
41 #include <libaegis/project/history.h>
42 #include <libaegis/sub.h>
43 #include <libaegis/user.h>
44 #include <libaegis/zero.h>
45
46 #include <aegis/aedn.h>
47
48
49 static void
delta_name_usage(void)50 delta_name_usage(void)
51 {
52 const char *progname;
53
54 progname = progname_get();
55 fprintf
56 (
57 stderr,
58 "usage: %s -Delta_Name [ <option>... ][ <delta_number> ] <string>...\n",
59 progname
60 );
61 fprintf(stderr, " %s -Delta_Name -List [ <option>... ]\n", progname);
62 fprintf(stderr, " %s -Delta_Name -Help\n", progname);
63 quit(1);
64 }
65
66
67 static void
delta_name_help(void)68 delta_name_help(void)
69 {
70 help("aedn", delta_name_usage);
71 }
72
73
74 static void
delta_name_list(void)75 delta_name_list(void)
76 {
77 trace(("delta_name_list()\n{\n"));
78 arglex();
79 change_identifier cid;
80 cid.command_line_parse_rest(delta_name_usage);
81 list_project_history(cid, 0);
82 trace(("}\n"));
83 }
84
85
86 static void
delta_name_main(void)87 delta_name_main(void)
88 {
89 trace(("delta_name_main()\n{\n"));
90 arglex();
91 bool stomp = false;
92 change_identifier cid;
93 nstring new_name;
94 while (arglex_token != arglex_token_eoln)
95 {
96 switch (arglex_token)
97 {
98 default:
99 generic_argument(delta_name_usage);
100 continue;
101
102 case arglex_token_overwriting:
103 if (stomp)
104 duplicate_option(delta_name_usage);
105 stomp = true;
106 break;
107
108 case arglex_token_string:
109 if (!new_name.empty())
110 {
111 error_intl(0, i18n("too many delta names"));
112 delta_name_usage();
113 }
114 new_name = arglex_value.alv_string;
115 break;
116
117 case arglex_token_delta:
118 case arglex_token_number:
119 case arglex_token_change:
120 case arglex_token_delta_from_change:
121 case arglex_token_delta_date:
122 case arglex_token_project:
123 cid.command_line_parse(delta_name_usage);
124 continue;
125
126 case arglex_token_wait:
127 case arglex_token_wait_not:
128 user_ty::lock_wait_argument(delta_name_usage);
129 break;
130 }
131 arglex();
132 }
133 cid.command_line_check(delta_name_usage);
134 if (new_name.empty())
135 {
136 error_intl(0, i18n("no delta name"));
137 delta_name_usage();
138 }
139
140 //
141 // If the user did not nominate a specific change set, then we take
142 // the head of the branch (most recent integration) as the change
143 // the label is to be attached to.
144 //
145 if (!cid.set())
146 cid.set_delta_from_branch_head();
147
148 //
149 // lock the project file
150 //
151 cid.get_pp()->pstate_lock_prepare();
152 lock_take();
153
154 //
155 // it is an error if the user is not a project administrator
156 //
157 if (!project_administrator_query(cid.get_pp(), cid.get_up()->name()))
158 project_fatal(cid.get_pp(), 0, i18n("not an administrator"));
159
160 //
161 // find the delta number
162 //
163 long delta_number = cid.get_cp()->delta_number_get();
164 if (delta_number <= 0)
165 {
166 change_fatal(cid.get_cp(), 0, i18n("aedn bad state"));
167 }
168
169 //
170 // Make sure the name has not been used already.
171 //
172 if (!stomp)
173 {
174 long other =
175 project_history_delta_by_name(cid.get_pp(), new_name.get_ref(), 1);
176 if (other && other != delta_number)
177 {
178 sub_context_ty sc;
179 sc.var_set_string("Name", new_name);
180 sc.var_set_long("Number", delta_number);
181 sc.var_optional("Number");
182 sc.var_set_long("Other", other);
183 sc.var_optional("Other");
184 project_fatal(cid.get_pp(), &sc, i18n("delta $name in use"));
185 // NOTREACHED
186 }
187 }
188 project_history_delta_name_delete(cid.get_pp(), new_name.get_ref());
189
190 //
191 // add the name to the selected history entry
192 //
193 project_history_delta_name_add
194 (
195 cid.get_pp(),
196 delta_number,
197 new_name.get_ref()
198 );
199
200 //
201 // If the history label command is defined,
202 // label each of the project files.
203 //
204 pconf_ty *pconf_data = project_pconf_get(cid.get_pp());
205 if (pconf_data->history_label_command)
206 {
207 time_t delta_date =
208 project_history_delta_to_timestamp(cid.get_pp(), delta_number);
209 project_file_roll_forward historian(cid.get_pp(), delta_date, 0);
210 for (size_t j = 0;; j++)
211 {
212 fstate_src_ty *src = cid.get_pp()->file_nth(j, view_path_simple);
213 if (!src)
214 break;
215 file_event *fep = historian.get_last(src->file_name);
216 if (!fep)
217 {
218 //
219 // File not yet created at this delta.
220 //
221 continue;
222 }
223 src = fep->get_src();
224 assert(src);
225 switch (src->action)
226 {
227 case file_action_remove:
228 //
229 // File removed before this delta.
230 //
231 continue;
232
233 case file_action_create:
234 case file_action_modify:
235 case file_action_insulate:
236 case file_action_transparent:
237 break;
238 }
239
240 //
241 // Label everything else.
242 //
243 change_run_history_label_command
244 (
245 fep->get_change(),
246 src,
247 new_name.get_ref()
248 );
249 }
250 }
251
252 //
253 // release the locks
254 //
255 cid.get_pp()->pstate_write();
256 commit();
257 lock_release();
258
259 //
260 // verbose success message
261 //
262 {
263 sub_context_ty sc;
264 sc.var_set_string("Name", new_name);
265 sc.var_optional("Name");
266 sc.var_set_long("Number", delta_number);
267 sc.var_optional("Number");
268 project_verbose(cid.get_pp(), &sc, i18n("delta name complete"));
269 }
270 trace(("}\n"));
271 }
272
273
274 void
delta_name_assignment(void)275 delta_name_assignment(void)
276 {
277 static arglex_dispatch_ty dispatch[] =
278 {
279 { arglex_token_help, delta_name_help, 0 },
280 { arglex_token_list, delta_name_list, 0 },
281 };
282
283 trace(("delta_name_assignment()\n{\n"));
284 arglex_dispatch(dispatch, SIZEOF(dispatch), delta_name_main);
285 trace(("}\n"));
286 }
287
288
289 // vim: set ts=8 sw=4 et :
290