comparison host/tools/configtool/standalone/common/cdl_exec.cxx @ 105:5a0cc6c243a9 ecos-sw-2000-06-30

Merge from eCos master repository on 2000-06-30-08:18:49-BST
author jlarmour
date Fri, 30 Jun 2000 16:27:35 +0000
parents 95f3e12a6327
children 84e4bde58b26
comparison
equal deleted inserted replaced
104:ad66e26a9e7c 105:5a0cc6c243a9
37 // 37 //
38 //####DESCRIPTIONEND#### 38 //####DESCRIPTIONEND####
39 //========================================================================== 39 //==========================================================================
40 40
41 #ifdef _MSC_VER 41 #ifdef _MSC_VER
42 #include <direct.h> /* for getcwd() */ 42 #include <direct.h> /* for getcwd() */
43 #else 43 #else
44 #include <unistd.h> /* for getcwd() */ 44 #include <unistd.h> /* for getcwd() */
45 #endif 45 #endif
46 #ifdef __CYGWIN__ 46 #ifdef __CYGWIN__
47 #include <sys/cygwin.h> /* for cygwin_conv_to_win32_path() */ 47 #include <windows.h>
48 #include <sys/cygwin.h> /* for cygwin_conv_to_win32_path() */
48 #endif 49 #endif
49 #include "build.hxx" 50 #include "build.hxx"
50 #include "cdl_exec.hxx" 51 #include "cdl_exec.hxx"
51 52
52 cdl_exec::cdl_exec (const std::string repository_tree, const std::string savefile_name, const std::string install_tree, bool no_resolve) : 53 // ----------------------------------------------------------------------------
53 pkgdata (NULL), 54 bool cdl_exec::quiet = false;
54 interp (NULL), 55 bool cdl_exec::verbose = false;
55 config (NULL) { 56 bool cdl_exec::ignore_errors = false;
56 repository = repository_tree; 57
57 savefile = savefile_name; 58 cdl_exec::cdl_exec (const std::string repository_arg, const std::string savefile_arg,
58 install_prefix = install_tree; 59 const std::string install_arg, bool no_resolve_arg)
59 CdlTransactionBody::set_inference_callback_fn (&inference_callback); 60 : repository(repository_arg),
60 if (no_resolve) { 61 savefile(savefile_arg),
61 CdlTransactionBody::disable_automatic_inference (); 62 install_prefix(install_arg),
62 } 63 no_resolve(no_resolve_arg),
63 } 64 pkgdata (NULL),
64 65 interp (NULL),
65 bool cdl_exec::cmd_new (const std::string cdl_hardware, const std::string cdl_template /* = "default" */, const std::string cdl_version /* = "" */) { 66 config (NULL)
66 bool status = false; 67 {
67 try { 68
68 pkgdata = CdlPackagesDatabaseBody::make (repository, &diagnostic_handler, &diagnostic_handler); 69 // The inference callback does not actually do anything at present.
69 interp = CdlInterpreterBody::make (); 70 // In future it may be useful for diagnostic purposes.
70 config = CdlConfigurationBody::make ("eCos", pkgdata, interp); 71 CdlTransactionBody::set_inference_callback_fn (&inference_callback);
71 config->set_hardware (resolve_hardware_alias (cdl_hardware), &diagnostic_handler, &diagnostic_handler); 72
72 if (pkgdata->is_known_template (cdl_template) && ! cdl_version.empty ()) { 73 // Automatic inference is always disabled. The inference engine
73 const std::vector<std::string> & versions = pkgdata->get_template_versions (cdl_template); 74 // only gets invoked explicitly, after a suitable transaction callback
74 if (versions.end () == std::find (versions.begin (), versions.end (), cdl_version)) { 75 // has been invoked. The problem here is that the transaction callback
75 throw CdlStringException ("Unknown version " + cdl_version); 76 // has to report changes made by the inference engine but there is
76 } 77 // no way of distinguishing between inferred values that come out of
77 } 78 // savefiles and inferred values determined by the inference engine.
78 config->set_template (cdl_template, cdl_version, &diagnostic_handler, &diagnostic_handler); 79 CdlTransactionBody::disable_automatic_inference ();
79 config->save (savefile); 80 }
80 status = true; 81
81 } catch (CdlStringException exception) { 82 void
82 exception_handler (exception); 83 cdl_exec::set_quiet_mode(bool new_val)
83 } catch (...) { 84 {
84 exception_handler (); 85 quiet = new_val;
85 } 86 }
86 87
87 delete_cdl_data (); 88 void
88 return status; 89 cdl_exec::set_verbose_mode(bool new_val)
89 } 90 {
90 91 verbose = new_val;
91 bool cdl_exec::cmd_target (const std::string cdl_target) { 92 }
92 bool status = false; 93
93 try { 94 void
94 pkgdata = CdlPackagesDatabaseBody::make (repository, &diagnostic_handler, &diagnostic_handler); 95 cdl_exec::set_ignore_errors_mode(bool new_val)
95 interp = CdlInterpreterBody::make (); 96 {
96 config = CdlConfigurationBody::load (savefile, pkgdata, interp, &diagnostic_handler, &diagnostic_handler); 97 ignore_errors = new_val;
97 config->set_hardware (resolve_hardware_alias (cdl_target), &diagnostic_handler, &diagnostic_handler); 98 }
98 config->save (savefile); 99
99 status = true; 100 // ----------------------------------------------------------------------------
100 } catch (CdlStringException exception) { 101 void
101 exception_handler (exception); 102 cdl_exec::init(bool load_config)
102 } catch (...) { 103 {
103 exception_handler (); 104 pkgdata = CdlPackagesDatabaseBody::make(repository, &diagnostic_handler, &diagnostic_handler);
104 } 105 interp = CdlInterpreterBody::make();
105 106 if (load_config) {
106 delete_cdl_data (); 107 config = CdlConfigurationBody::load (savefile, pkgdata, interp, &diagnostic_handler, &diagnostic_handler);
107 return status; 108 }
108 } 109 }
109 110
110 bool cdl_exec::cmd_template (const std::string cdl_template, const std::string cdl_version /* = "" */) { 111 // ----------------------------------------------------------------------------
111 bool status = false; 112 void
112 try { 113 cdl_exec::delete_cdl_data ()
113 pkgdata = CdlPackagesDatabaseBody::make (repository, &diagnostic_handler, &diagnostic_handler); 114 {
114 interp = CdlInterpreterBody::make (); 115 if (0 != config) {
115 config = CdlConfigurationBody::load (savefile, pkgdata, interp, &diagnostic_handler, &diagnostic_handler); 116 delete config;
116 if (pkgdata->is_known_template (cdl_template) && ! cdl_version.empty ()) { 117 config = 0;
117 const std::vector<std::string> & versions = pkgdata->get_template_versions (cdl_template); 118 }
118 if (versions.end () == std::find (versions.begin (), versions.end (), cdl_version)) { 119 if (0 != interp) {
119 throw CdlStringException ("Unknown version " + cdl_version); 120 delete interp;
120 } 121 interp = 0;
121 } 122 }
122 config->set_template (cdl_template, cdl_version, &diagnostic_handler, &diagnostic_handler); 123 if (0 != pkgdata) {
123 config->save (savefile); 124 delete pkgdata;
124 status = true; 125 pkgdata = 0;
125 } catch (CdlStringException exception) { 126 }
126 exception_handler (exception); 127 }
127 } catch (...) { 128
128 exception_handler (); 129 // ----------------------------------------------------------------------------
129 } 130 bool cdl_exec::cmd_new (const std::string cdl_hardware,
130 131 const std::string cdl_template /* = "default" */,
131 delete_cdl_data (); 132 const std::string cdl_version /* = "" */)
132 return status; 133 {
133 } 134 bool status = false;
134 135 try {
135 bool cdl_exec::cmd_export (const std::string cdl_savefile) { 136 init(false);
136 bool status = false; 137
137 try { 138 config = CdlConfigurationBody::make ("eCos", pkgdata, interp);
138 pkgdata = CdlPackagesDatabaseBody::make (repository, &diagnostic_handler, &diagnostic_handler); 139
139 interp = CdlInterpreterBody::make (); 140 // The hardware and template should be loaded in a single transaction.
140 config = CdlConfigurationBody::load (savefile, pkgdata, interp, &diagnostic_handler, &diagnostic_handler); 141 // Validating the target name etc. can be left to libcdl.
141 config->save (cdl_savefile, /* minimal = */ true); 142 CdlTransaction transact = CdlTransactionBody::make(config);
142 status = true; 143 config->set_hardware(transact, resolve_hardware_alias(cdl_hardware), &diagnostic_handler, &diagnostic_handler);
143 } catch (CdlStringException exception) { 144 config->set_template(transact, cdl_template, cdl_version, &diagnostic_handler, &diagnostic_handler);
144 exception_handler (exception); 145 transact->body();
145 } catch (...) { 146 delete transact;
146 exception_handler (); 147
147 } 148 // Unless inference has been suppressed, make sure that the
148 149 // inference engine gets invoked and that its results get
149 delete_cdl_data (); 150 // reported.
150 return status; 151 if (!no_resolve) {
151 } 152 CdlTransactionBody::set_callback_fn(&transaction_callback);
152 153 config->resolve_all_conflicts();
153 bool cdl_exec::cmd_import (const std::string cdl_savefile) { 154 }
154 bool status = false; 155
155 try { 156 // Now report any conflicts which the inference engine could not report.
156 pkgdata = CdlPackagesDatabaseBody::make (repository, &diagnostic_handler, &diagnostic_handler); 157 report_conflicts();
157 interp = CdlInterpreterBody::make (); 158
158 config = CdlConfigurationBody::load (savefile, pkgdata, interp, &diagnostic_handler, &diagnostic_handler); 159 // A savefile should be generated/updated even if there are conflicts.
159 config->add (cdl_savefile, &diagnostic_handler, &diagnostic_handler); 160 // Otherwise the user does not have a chance to edit the savefile
160 config->save (savefile); 161 // and fix things.
161 status = true; 162 config->save (savefile);
162 } catch (CdlStringException exception) { 163 if (ignore_errors || (0 == config->get_all_conflicts().size())) {
163 exception_handler (exception); 164 status = true;
164 } catch (...) { 165 }
165 exception_handler (); 166 } catch (CdlStringException exception) {
166 } 167 exception_handler (exception);
167 168 } catch (...) {
168 delete_cdl_data (); 169 exception_handler ();
169 return status; 170 }
170 } 171
171 172 delete_cdl_data ();
172 bool cdl_exec::cmd_add (const std::vector<std::string> cdl_packages) { 173 return status;
173 bool status = false; 174 }
174 try { 175
175 pkgdata = CdlPackagesDatabaseBody::make (repository, &diagnostic_handler, &diagnostic_handler); 176 // ----------------------------------------------------------------------------
176 interp = CdlInterpreterBody::make (); 177 bool
177 config = CdlConfigurationBody::load (savefile, pkgdata, interp, &diagnostic_handler, &diagnostic_handler); 178 cdl_exec::cmd_target (const std::string cdl_target)
178 for (unsigned int n = 0; n < cdl_packages.size (); n++) { 179 {
179 config->load_package (resolve_package_alias (cdl_packages [n]), "", &diagnostic_handler, &diagnostic_handler); 180 bool status = false;
180 } 181 try {
181 config->save (savefile); 182 init(true);
182 status = true; 183 config->set_hardware (resolve_hardware_alias (cdl_target), &diagnostic_handler, &diagnostic_handler);
183 } catch (CdlStringException exception) { 184 if (!no_resolve) {
184 exception_handler (exception); 185 CdlTransactionBody::set_callback_fn(&transaction_callback);
185 } catch (...) { 186 config->resolve_all_conflicts();
186 exception_handler (); 187 }
187 } 188 report_conflicts();
188 189 config->save (savefile);
189 delete_cdl_data (); 190 if (ignore_errors || (0 == config->get_all_conflicts().size())) {
190 return status; 191 status = true;
191 } 192 }
192 193 } catch (CdlStringException exception) {
193 bool cdl_exec::cmd_remove (const std::vector<std::string> cdl_packages) { 194 exception_handler (exception);
194 unsigned int n; 195 } catch (...) {
195 bool status = false; 196 exception_handler ();
196 try { 197 }
197 pkgdata = CdlPackagesDatabaseBody::make (repository, &diagnostic_handler, &diagnostic_handler); 198
198 interp = CdlInterpreterBody::make (); 199 delete_cdl_data ();
199 config = CdlConfigurationBody::load (savefile, pkgdata, interp, &diagnostic_handler, &diagnostic_handler); 200 return status;
200 for (n = 0; n < cdl_packages.size (); n++) { 201 }
201 if (! config->lookup (resolve_package_alias (cdl_packages [n]))) { 202
202 throw CdlStringException ("Unknown package " + cdl_packages [n]); 203 // ----------------------------------------------------------------------------
203 } 204 bool
204 } 205 cdl_exec::cmd_template (const std::string cdl_template, const std::string cdl_version /* = "" */)
205 for (n = 0; n < cdl_packages.size (); n++) { 206 {
206 config->unload_package (resolve_package_alias (cdl_packages [n])); 207 bool status = false;
207 } 208 try {
208 config->save (savefile); 209 init(true);
209 status = true; 210 config->set_template (cdl_template, cdl_version, &diagnostic_handler, &diagnostic_handler);
210 } catch (CdlStringException exception) { 211 if (!no_resolve) {
211 exception_handler (exception); 212 CdlTransactionBody::set_callback_fn(&transaction_callback);
212 } catch (...) { 213 config->resolve_all_conflicts();
213 exception_handler (); 214 }
214 } 215 report_conflicts();
215 216 config->save (savefile);
216 delete_cdl_data (); 217 if (ignore_errors || (0 == config->get_all_conflicts().size())) {
217 return status; 218 status = true;
218 } 219 }
219 220 } catch (CdlStringException exception) {
220 bool cdl_exec::cmd_version (const std::string cdl_version, const std::vector<std::string> cdl_packages) { 221 exception_handler (exception);
221 bool status = false; 222 } catch (...) {
222 try { 223 exception_handler ();
223 pkgdata = CdlPackagesDatabaseBody::make (repository, &diagnostic_handler, &diagnostic_handler); 224 }
224 interp = CdlInterpreterBody::make (); 225
225 config = CdlConfigurationBody::load (savefile, pkgdata, interp, &diagnostic_handler, &diagnostic_handler); 226 delete_cdl_data ();
226 for (unsigned int n = 0; n < cdl_packages.size (); n++) { 227 return status;
227 config->change_package_version (resolve_package_alias (cdl_packages [n]), cdl_version, &diagnostic_handler, &diagnostic_handler, true); 228 }
228 } 229
229 config->save (savefile); 230 // ----------------------------------------------------------------------------
230 status = true; 231 bool
231 } catch (CdlStringException exception) { 232 cdl_exec::cmd_export (const std::string cdl_savefile)
232 exception_handler (exception); 233 {
233 } catch (...) { 234 bool status = false;
234 exception_handler (); 235 try {
235 } 236 init(true);
236 237 if (!no_resolve) {
237 delete_cdl_data (); 238 CdlTransactionBody::set_callback_fn(&transaction_callback);
238 return status; 239 config->resolve_all_conflicts();
239 } 240 }
240 241 report_conflicts();
241 bool cdl_exec::cmd_tree () { 242 // Exporting to another file should only happen if the
242 bool status = false; 243 // configuration is conflict-free. This is different from
243 try { 244 // updating the savefile.
244 pkgdata = CdlPackagesDatabaseBody::make (repository, &diagnostic_handler, &diagnostic_handler); 245 if (ignore_errors || (0 == config->get_all_conflicts().size())) {
245 interp = CdlInterpreterBody::make (); 246 config->save (cdl_savefile, /* minimal = */ true);
246 config = CdlConfigurationBody::load (savefile, pkgdata, interp, &diagnostic_handler, &diagnostic_handler); 247 status = true;
248 }
249 } catch (CdlStringException exception) {
250 exception_handler (exception);
251 } catch (...) {
252 exception_handler ();
253 }
254
255 delete_cdl_data ();
256 return status;
257 }
258
259 // ----------------------------------------------------------------------------
260 bool
261 cdl_exec::cmd_import (const std::string cdl_savefile)
262 {
263 bool status = false;
264 try {
265 init(true);
266 config->add(cdl_savefile, &diagnostic_handler, &diagnostic_handler);
267 if (!no_resolve) {
268 CdlTransactionBody::set_callback_fn(&transaction_callback);
269 config->resolve_all_conflicts();
270 }
271 report_conflicts();
272 config->save (savefile);
273 if (ignore_errors || (0 == config->get_all_conflicts().size())) {
274 status = true;
275 }
276 } catch (CdlStringException exception) {
277 exception_handler (exception);
278 } catch (...) {
279 exception_handler ();
280 }
281
282 delete_cdl_data ();
283 return status;
284 }
285
286 // ----------------------------------------------------------------------------
287 bool
288 cdl_exec::cmd_add (const std::vector<std::string> cdl_packages)
289 {
290 bool status = false;
291 try {
292 init(true);
293 for (unsigned int n = 0; n < cdl_packages.size (); n++) {
294 config->load_package (resolve_package_alias (cdl_packages [n]), "", &diagnostic_handler, &diagnostic_handler);
295 }
296 if (!no_resolve) {
297 CdlTransactionBody::set_callback_fn(&transaction_callback);
298 config->resolve_all_conflicts();
299 }
300 report_conflicts();
301 config->save (savefile);
302 if (ignore_errors || (0 == config->get_all_conflicts().size())) {
303 status = true;
304 }
305 } catch (CdlStringException exception) {
306 exception_handler (exception);
307 } catch (...) {
308 exception_handler ();
309 }
310
311 delete_cdl_data ();
312 return status;
313 }
314
315 // ----------------------------------------------------------------------------
316 bool
317 cdl_exec::cmd_remove (const std::vector<std::string> cdl_packages)
318 {
319 unsigned int n;
320 bool status = false;
321 try {
322 init(true);
323 for (n = 0; n < cdl_packages.size (); n++) {
324 if (! config->lookup (resolve_package_alias (cdl_packages [n]))) {
325 throw CdlStringException ("Unknown package " + cdl_packages [n]);
326 }
327 }
328 for (n = 0; n < cdl_packages.size (); n++) {
329 config->unload_package (resolve_package_alias (cdl_packages [n]));
330 }
331 if (!no_resolve) {
332 CdlTransactionBody::set_callback_fn(&transaction_callback);
333 config->resolve_all_conflicts();
334 }
335 report_conflicts();
336 config->save (savefile);
337 if (ignore_errors || (0 == config->get_all_conflicts().size())) {
338 status = true;
339 }
340 } catch (CdlStringException exception) {
341 exception_handler (exception);
342 } catch (...) {
343 exception_handler ();
344 }
345
346 delete_cdl_data ();
347 return status;
348 }
349
350 // ----------------------------------------------------------------------------
351 bool
352 cdl_exec::cmd_version (const std::string cdl_version, const std::vector<std::string> cdl_packages)
353 {
354 bool status = false;
355 try {
356 init(true);
357 for (unsigned int n = 0; n < cdl_packages.size (); n++) {
358 config->change_package_version(resolve_package_alias (cdl_packages [n]), cdl_version,
359 &diagnostic_handler, &diagnostic_handler, true);
360 }
361 if (!no_resolve) {
362 CdlTransactionBody::set_callback_fn(&transaction_callback);
363 config->resolve_all_conflicts();
364 }
365 report_conflicts();
366 config->save (savefile);
367 if (ignore_errors || (0 == config->get_all_conflicts().size())) {
368 status = true;
369 }
370 } catch (CdlStringException exception) {
371 exception_handler (exception);
372 } catch (...) {
373 exception_handler ();
374 }
375
376 delete_cdl_data ();
377 return status;
378 }
379
380 // ----------------------------------------------------------------------------
381 bool
382 cdl_exec::cmd_tree ()
383 {
384 bool status = false;
385 try {
386 init(true);
387 if (!no_resolve) {
388 CdlTransactionBody::set_callback_fn(&transaction_callback);
389 config->resolve_all_conflicts();
390 }
391 report_conflicts();
392 config->save (savefile);
393 // A build tree should only be generated if there are no conflicts.
394 if (ignore_errors || (0 == config->get_all_conflicts().size())) {
247 #ifdef _MSC_VER 395 #ifdef _MSC_VER
248 char cwd [_MAX_PATH + 1]; 396 char cwd [_MAX_PATH + 1];
249 #else 397 #else
250 char cwd [PATH_MAX + 1]; 398 char cwd [PATH_MAX + 1];
251 #endif 399 #endif
252 getcwd (cwd, sizeof cwd); 400 getcwd (cwd, sizeof cwd);
253 #ifdef __CYGWIN__ 401 #ifdef __CYGWIN__
254 char cwd_win32 [MAXPATHLEN + 1]; 402 char cwd_win32 [MAXPATHLEN + 1];
255 cygwin_conv_to_win32_path (cwd, cwd_win32); 403 cygwin_conv_to_win32_path (cwd, cwd_win32);
256 generate_build_tree (config, cwd_win32, install_prefix); 404 generate_build_tree (config, cwd_win32, install_prefix);
257 #else 405 #else
258 generate_build_tree (config, cwd, install_prefix); 406 generate_build_tree (config, cwd, install_prefix);
259 #endif 407 #endif
260 config->generate_config_headers (install_prefix.empty () ? "install/include/pkgconf" : install_prefix + "/include/pkgconf"); 408 config->generate_config_headers (install_prefix.empty () ? "install/include/pkgconf" : install_prefix + "/include/pkgconf");
261 status = true; 409 status = true;
262 } catch (CdlStringException exception) { 410 } else {
263 exception_handler (exception); 411 printf("\nUnable to generate build tree, this configuration still contains conflicts.\n");
264 } catch (...) { 412 printf("Either resolve the conflicts or use --ignore-errors\n");
265 exception_handler (); 413 }
266 } 414 } catch (CdlStringException exception) {
267 415 exception_handler (exception);
268 delete_cdl_data (); 416 } catch (...) {
269 return status; 417 exception_handler ();
270 } 418 }
271 419
272 bool cdl_exec::cmd_list () { 420 delete_cdl_data ();
273 bool status = false; 421 return status;
274 try { 422 }
275 pkgdata = CdlPackagesDatabaseBody::make (repository, &diagnostic_handler, &diagnostic_handler); 423
276 424 // ----------------------------------------------------------------------------
277 // list the installed packages 425 bool
278 std::vector<std::string> packages = pkgdata->get_packages (); 426 cdl_exec::cmd_list ()
279 std::sort (packages.begin (), packages.end ()); 427 {
280 for (unsigned int package = 0; package < packages.size (); package++) { 428 bool status = false;
281 const std::vector<std::string> & aliases = pkgdata->get_package_aliases (packages [package]); 429 try {
282 printf ("Package %s (%s):\n aliases:", packages [package].c_str (), aliases [0].c_str ()); 430 init(false);
283 for (unsigned int alias = 1; alias < aliases.size (); alias++) { 431
284 printf (" %s", aliases [alias].c_str ()); 432 // list the installed packages
285 } 433 std::vector<std::string> packages = pkgdata->get_packages ();
286 const std::vector<std::string> & versions = pkgdata->get_package_versions (packages [package]); 434 std::sort (packages.begin (), packages.end ());
287 printf ("\n versions:"); 435 for (unsigned int package = 0; package < packages.size (); package++) {
288 for (unsigned int version = 0; version < versions.size (); version++) { 436 const std::vector<std::string> & aliases = pkgdata->get_package_aliases (packages [package]);
289 printf (" %s", versions [version].c_str ()); 437 printf ("Package %s (%s):\n aliases:", packages [package].c_str (), aliases [0].c_str ());
290 } 438 for (unsigned int alias = 1; alias < aliases.size (); alias++) {
291 printf ("\n"); 439 printf (" %s", aliases [alias].c_str ());
292 } 440 }
293 441 const std::vector<std::string> & versions = pkgdata->get_package_versions (packages [package]);
294 // list the available targets 442 printf ("\n versions:");
295 std::vector<std::string> targets = pkgdata->get_targets (); 443 for (unsigned int version = 0; version < versions.size (); version++) {
296 std::sort (targets.begin (), targets.end ()); 444 printf (" %s", versions [version].c_str ());
297 for (unsigned int target = 0; target < targets.size (); target++) { 445 }
298 const std::vector<std::string> & aliases = pkgdata->get_target_aliases (targets [target]); 446 printf ("\n");
299 printf ("Target %s (%s):\n aliases:", targets [target].c_str (), aliases [0].c_str ()); 447 }
300 for (unsigned int alias = 1; alias < aliases.size (); alias++) { 448
301 printf (" %s", aliases [alias].c_str ()); 449 // list the available targets
302 } 450 std::vector<std::string> targets = pkgdata->get_targets ();
303 printf ("\n"); 451 std::sort (targets.begin (), targets.end ());
304 } 452 for (unsigned int target = 0; target < targets.size (); target++) {
305 453 const std::vector<std::string> & aliases = pkgdata->get_target_aliases (targets [target]);
306 // list the available templates 454 printf ("Target %s (%s):\n aliases:", targets [target].c_str (), aliases [0].c_str ());
307 std::vector<std::string> templates = pkgdata->get_templates (); 455 for (unsigned int alias = 1; alias < aliases.size (); alias++) {
308 std::sort (templates.begin (), templates.end ()); 456 printf (" %s", aliases [alias].c_str ());
309 for (unsigned int templ = 0; templ < templates.size (); templ++) { 457 }
310 const std::vector<std::string> & versions = pkgdata->get_template_versions (templates [templ]); 458 printf ("\n");
311 printf ("Template %s:\n versions:", templates [templ].c_str ()); 459 }
312 for (unsigned int version = 0; version < versions.size (); version++) { 460
313 printf (" %s", versions [version].c_str ()); 461 // list the available templates
314 } 462 std::vector<std::string> templates = pkgdata->get_templates ();
315 printf ("\n"); 463 std::sort (templates.begin (), templates.end ());
316 } 464 for (unsigned int templ = 0; templ < templates.size (); templ++) {
317 465 const std::vector<std::string> & versions = pkgdata->get_template_versions (templates [templ]);
318 status = true; 466 printf ("Template %s:\n versions:", templates [templ].c_str ());
319 } catch (CdlStringException exception) { 467 for (unsigned int version = 0; version < versions.size (); version++) {
320 exception_handler (exception); 468 printf (" %s", versions [version].c_str ());
321 } catch (...) { 469 }
322 exception_handler (); 470 printf ("\n");
323 } 471 }
324 472
325 delete_cdl_data (); 473 status = true;
326 return status; 474 } catch (CdlStringException exception) {
327 } 475 exception_handler (exception);
328 476 } catch (...) {
329 bool cdl_exec::cmd_check () { 477 exception_handler ();
330 bool status = false; 478 }
331 unsigned int n; 479
332 480 delete_cdl_data ();
333 try { 481 return status;
334 CdlTransactionBody::disable_automatic_inference (); 482 }
335 pkgdata = CdlPackagesDatabaseBody::make (repository, &diagnostic_handler, &diagnostic_handler); 483
336 interp = CdlInterpreterBody::make (); 484 // ----------------------------------------------------------------------------
337 config = CdlConfigurationBody::load (savefile, pkgdata, interp, &diagnostic_handler, &diagnostic_handler); 485 bool
338 config->save (savefile); // tidy up any manual edits 486 cdl_exec::cmd_check ()
339 487 {
340 // report current target and template 488 bool status = false;
341 printf ("Target: %s\n", config->get_hardware ().c_str ()); 489 unsigned int n;
342 printf ("Template: %s\n", config->get_template ().c_str ()); 490
343 std::vector<std::string> template_packages = pkgdata->get_template_packages (config->get_template ()); 491 try {
344 const std::vector<std::string> & hardware_packages = pkgdata->get_target_packages (config->get_hardware ()); 492 init(true);
345 for (n = 0; n < hardware_packages.size (); n++) { 493 // check() should never invoke the inference engine. The user
346 template_packages.push_back (hardware_packages [n]); 494 // wants to determine the current status, which should not
347 } 495 // change.
348 496 // However, updating the savefile is worthwhile because it
349 // report loaded packages not in the templates 497 // will now contain more accurate information about the state.
350 const std::vector<CdlLoadable> & loadables = config->get_loadables (); 498 config->save (savefile);
351 std::vector<std::string> added_packages; 499
352 std::vector<CdlLoadable>::const_iterator loadable_i; 500 // report current target and template
353 for (loadable_i = loadables.begin (); loadable_i != loadables.end (); loadable_i++) { 501 printf ("Target: %s\n", config->get_hardware ().c_str ());
354 const CdlNode & node = dynamic_cast<CdlNode> (* loadable_i); 502 printf ("Template: %s\n", config->get_template ().c_str ());
355 if (template_packages.end () == std::find (template_packages.begin (), template_packages.end (), node->get_name ())) { 503 std::vector<std::string> template_packages = pkgdata->get_template_packages (config->get_template ());
356 added_packages.push_back (node->get_name ()); 504 const std::vector<std::string> & hardware_packages = pkgdata->get_target_packages (config->get_hardware ());
357 } 505 for (n = 0; n < hardware_packages.size (); n++) {
358 } 506 template_packages.push_back (hardware_packages [n]);
359 if (added_packages.size ()) { 507 }
360 printf ("Added:\n"); 508
361 } 509 // report loaded packages not in the templates
362 for (n = 0; n < added_packages.size (); n++) { 510 const std::vector<CdlLoadable> & loadables = config->get_loadables ();
363 printf (" %s\n", added_packages [n].c_str ()); 511 std::vector<std::string> added_packages;
364 } 512 std::vector<CdlLoadable>::const_iterator loadable_i;
365 513 for (loadable_i = loadables.begin (); loadable_i != loadables.end (); loadable_i++) {
366 // report template packages not in the configuration 514 const CdlNode & node = dynamic_cast<CdlNode> (* loadable_i);
367 std::vector<std::string> removed_packages; 515 if (template_packages.end () == std::find (template_packages.begin (), template_packages.end (), node->get_name ())) {
368 for (n = 0; n < template_packages.size (); n++) { 516 added_packages.push_back (node->get_name ());
369 if (! config->lookup (template_packages [n])) { 517 }
370 removed_packages.push_back (template_packages [n]); 518 }
371 } 519 if (added_packages.size ()) {
372 } 520 printf ("Added:\n");
373 if (removed_packages.size ()) { 521 }
374 printf ("Removed:\n"); 522 for (n = 0; n < added_packages.size (); n++) {
375 } 523 printf (" %s\n", added_packages [n].c_str ());
376 for (n = 0; n < removed_packages.size (); n++) { 524 }
377 printf (" %s\n", removed_packages [n].c_str ()); 525
378 } 526 // report template packages not in the configuration
379 527 std::vector<std::string> removed_packages;
380 // report packages of non-default version 528 for (n = 0; n < template_packages.size (); n++) {
381 std::vector<CdlValuable> version_packages; 529 if (! config->lookup (template_packages [n])) {
382 for (loadable_i = loadables.begin (); loadable_i != loadables.end (); loadable_i++) { 530 removed_packages.push_back (template_packages [n]);
383 const CdlValuable & valuable = dynamic_cast<CdlValuable> (* loadable_i); 531 }
384 if (pkgdata->get_package_versions (valuable->get_name ()) [0] != valuable->get_value ()) { 532 }
385 version_packages.push_back (valuable); 533 if (removed_packages.size ()) {
386 } 534 printf ("Removed:\n");
387 } 535 }
388 if (version_packages.size ()) { 536 for (n = 0; n < removed_packages.size (); n++) {
389 printf ("Version(s):\n"); 537 printf (" %s\n", removed_packages [n].c_str ());
390 } 538 }
391 for (n = 0; n < version_packages.size (); n++) { 539
392 printf (" %s %s\n", version_packages [n]->get_name ().c_str (), version_packages [n]->get_value ().c_str ()); 540 // report packages of non-default version
393 } 541 std::vector<CdlValuable> version_packages;
394 542 for (loadable_i = loadables.begin (); loadable_i != loadables.end (); loadable_i++) {
395 // report conflicts 543 const CdlValuable & valuable = dynamic_cast<CdlValuable> (* loadable_i);
396 const std::list<CdlConflict> & conflicts = config->get_all_conflicts (); 544 if (pkgdata->get_package_versions (valuable->get_name ()) [0] != valuable->get_value ()) {
397 if (conflicts.size ()) { 545 version_packages.push_back (valuable);
398 printf ("%u conflict(s):\n", conflicts.size ()); 546 }
399 } else { 547 }
400 printf ("No conflicts\n"); 548 if (version_packages.size ()) {
401 } 549 printf ("Version(s):\n");
402 std::list<CdlConflict>::const_iterator conf_i; 550 }
403 for (conf_i = conflicts.begin (); conf_i != conflicts.end (); conf_i++) { // for each conflict 551 for (n = 0; n < version_packages.size (); n++) {
404 report_conflict (* conf_i); 552 printf (" %s %s\n", version_packages [n]->get_name ().c_str (), version_packages [n]->get_value ().c_str ());
405 } 553 }
406 554
407 status = true; 555 // report conflicts
408 } catch (CdlStringException exception) { 556 const std::list<CdlConflict> & conflicts = config->get_all_conflicts ();
409 exception_handler (exception); 557 if (conflicts.size ()) {
410 } catch (...) { 558 printf ("%u conflict(s):\n", conflicts.size ());
411 exception_handler (); 559 } else {
412 } 560 printf ("No conflicts\n");
413 561 }
414 delete_cdl_data (); 562 report_conflicts();
415 return status; 563
416 } 564 status = true;
417 565 } catch (CdlStringException exception) {
418 bool cdl_exec::cmd_resolve () { 566 exception_handler (exception);
419 bool status = false; 567 } catch (...) {
420 568 exception_handler ();
421 try { 569 }
422 pkgdata = CdlPackagesDatabaseBody::make (repository, &diagnostic_handler, &diagnostic_handler); 570
423 interp = CdlInterpreterBody::make (); 571 delete_cdl_data ();
424 config = CdlConfigurationBody::load (savefile, pkgdata, interp, &diagnostic_handler, &diagnostic_handler); 572 return status;
425 config->resolve_all_conflicts (); 573 }
426 config->save (savefile); 574
427 status = true; 575 // ----------------------------------------------------------------------------
428 } catch (CdlStringException exception) { 576 bool
429 exception_handler (exception); 577 cdl_exec::cmd_resolve ()
430 } catch (...) { 578 {
431 exception_handler (); 579 bool status = false;
432 } 580
433 581 try {
434 delete_cdl_data (); 582 init(true);
435 return status; 583 CdlTransactionBody::set_callback_fn(&transaction_callback);
436 } 584 config->resolve_all_conflicts ();
437 585 report_conflicts();
438 CdlInferenceCallbackResult cdl_exec::inference_callback (CdlTransaction transaction) { 586 config->save (savefile);
439 const std::vector<CdlConflict> & resolved_conflicts = transaction->get_resolved_conflicts (); 587 if (ignore_errors || (0 == config->get_all_conflicts().size())) {
440 588 status = true;
441 // report resolved conflicts 589 }
442 if (resolved_conflicts.size ()) { 590 } catch (CdlStringException exception) {
443 printf ("%u conflict(s) resolved:\n", resolved_conflicts.size ()); 591 exception_handler (exception);
444 } 592 } catch (...) {
445 for (unsigned int n = 0; n < resolved_conflicts.size (); n++) { 593 exception_handler ();
446 report_conflict (resolved_conflicts [n]); 594 }
447 } 595
448 596 delete_cdl_data ();
449 // accept all changes 597 return status;
450 return CdlInferenceCallbackResult_Continue; 598 }
451 } 599
452 600 // ----------------------------------------------------------------------------
453 void cdl_exec::report_conflict (CdlConflict conflict) { 601 // The inference callback. This could give some useful diagnostics, or it
454 printf (" %s:\n %s\n", conflict->get_node ()->get_name ().c_str (), conflict->get_explanation ().c_str ()); 602 // could do useful things when running in some interactive mode. In batch
455 } 603 // mode it should not do anything.
456 604
457 void cdl_exec::diagnostic_handler (std::string message) { 605 CdlInferenceCallbackResult
458 printf ("%s\n", message.c_str ()); 606 cdl_exec::inference_callback (CdlTransaction transaction)
607 {
608 return CdlInferenceCallbackResult_Continue;
609 }
610
611 // ----------------------------------------------------------------------------
612 // Output a message with indentation after newlines.
613 static void
614 dump_string(unsigned int indent, const std::string& str)
615 {
616 bool newline_pending = false;
617 unsigned int i, j;
618 for (i = 0; i < str.size(); i++) {
619 if (newline_pending) {
620 putchar('\n');
621 if ('\n' != str[i]) {
622 for (j = 0; j < indent; j++) {
623 putchar(' ');
624 }
625 }
626 newline_pending = false;
627 }
628 if ('\n' == str[i]) {
629 newline_pending = true;
630 } else {
631 putchar(str[i]);
632 }
633 }
634 if (newline_pending) {
635 putchar('\n'); // But not the indentation.
636 }
637 }
638
639 // ----------------------------------------------------------------------------
640 // The transaction callback. This should report any changes that have been
641 // made to the configuration. The amount of output depends on the verbosity
642 // level selected by the user.
643 //
644 // 1) quiet - no output at all
645 // 2) default - list updates done by the inference engine.
646 // 3) verbose - this does not currently add anything.
647 //
648 // There is no reporting of new or resolved conflicts. Resolved
649 // conflicts are probably of no interest in batch mode. New conflicts
650 // will be handled by report_conflicts(). There is also no information
651 // given about active state changes, although arguably there should be
652 // especially in the case of containers.
653
654 void
655 cdl_exec::transaction_callback(const CdlTransactionCallback& callback_data)
656 {
657 if (quiet) {
658 return;
659 }
660
661 unsigned int i;
662 for (i = 0; i < callback_data.value_changes.size(); i++) {
663 CdlValuable valuable = callback_data.value_changes[i];
664 if (CdlValueSource_Inferred == valuable->get_source()) {
665 std::string msg = std::string("U ") + valuable->get_name() + ", new inferred value ";
666 std::string value = valuable->get_value();
667 if ("" == value) {
668 msg += "\"\"";
669 } else {
670 msg += value;
671 }
672 msg += "\n";
673 dump_string(4, msg);
674 }
675 }
676 }
677
678 // ----------------------------------------------------------------------------
679 // Report the remaining conflicts in the configuration. These indicate
680 // problems that the user should fix before going further with the
681 // configuration, e.g. before generating a build tree.
682 //
683 // Quiet verbosity level has no effect on this, but at the verbose level
684 // it is a good idea to look for a possible solution to the conflict.
685
686
687 void
688 cdl_exec::report_conflicts()
689 {
690 const std::list<CdlConflict>& all_conflicts = config->get_all_conflicts();
691 std::list<CdlConflict>::const_iterator conf_i;
692 for (conf_i = all_conflicts.begin(); conf_i != all_conflicts.end(); conf_i++) {
693 CdlNode node = (*conf_i)->get_node();
694
695 std::string msg = std::string("C ") + node->get_name() + ", " + (*conf_i)->get_explanation() + "\n";
696 dump_string(2, msg);
697
698 if (verbose && (*conf_i)->resolution_implemented()) {
699 // See if there is a possible solution to this conflict.
700 // This involves creating a transaction, invoking the
701 // inference engine, and cancelling the transaction
702 // (thus making sure that nothing actually changes).
703 //
704 // NOTE: at some stage libcdl may keep track of solutions
705 // globally. However, although it will know when a solution
706 // becomes invalid it will not necessarily try to resolve
707 // all global conflicts after every change, so attempting
708 // to do this in a transaction may still be necessary.
709 CdlTransaction transact = CdlTransactionBody::make(config);
710 transact->resolve(*conf_i);
711 if ((*conf_i)->has_known_solution()) {
712 std::string soln_msg = " Possible solution:\n";
713 const std::vector<std::pair<CdlValuable, CdlValue> > & soln = (*conf_i)->get_solution();
714 unsigned int i;
715 for (i = 0; i < soln.size(); i++) {
716 soln_msg += soln[i].first->get_name() + " -> " + soln[i].second.get_value() + "\n";
717 }
718 #if 0
719 // FIXME: currently this member only works for nested sub-transactions.
720 if (transact->user_confirmation_required()) {
721 msg += "This change affects previous user settings.\n";
722 }
723 #endif
724 dump_string(4, soln_msg);
725 }
726 transact->cancel();
727 delete transact;
728 }
729 }
730 }
731
732 // ----------------------------------------------------------------------------
733 void
734 cdl_exec::diagnostic_handler (std::string message)
735 {
736 printf ("%s\n", message.c_str ());
459 } 737 }
460 738
461 void cdl_exec::exception_handler (CdlStringException exception) { 739 void cdl_exec::exception_handler (CdlStringException exception) {
462 printf ("%s\n", exception.get_message ().c_str ()); 740 printf ("%s\n", exception.get_message ().c_str ());
463 } 741 }
464 742
465 void cdl_exec::exception_handler () { 743 void
466 printf ("Unknown error\n"); 744 cdl_exec::exception_handler ()
467 } 745 {
468 746 printf ("Unknown error\n");
469 void cdl_exec::delete_cdl_data () { 747 }
470 delete config; 748
471 config = NULL; 749
472 delete interp; 750 // ----------------------------------------------------------------------------
473 interp = NULL; 751 std::string
474 delete pkgdata; 752 cdl_exec::resolve_package_alias (const std::string alias)
475 pkgdata = NULL; 753 {
476 } 754 std::string package = alias;
477 755
478 std::string cdl_exec::resolve_package_alias (const std::string alias) { 756 if (! pkgdata->is_known_package (alias)) { // if the alias is not a package name
479 std::string package = alias; 757 const std::vector<std::string> & packages = pkgdata->get_packages (); // get packages
480 758 for (unsigned int n = 0; n < packages.size (); n++) { // for each package
481 if (! pkgdata->is_known_package (alias)) { // if the alias is not a package name 759 const std::vector<std::string> & aliases = pkgdata->get_package_aliases (packages [n]); // get package aliases
482 const std::vector<std::string> & packages = pkgdata->get_packages (); // get packages 760 if (aliases.end () != std::find (aliases.begin (), aliases.end (), alias)) { // if alias is found
483 for (unsigned int n = 0; n < packages.size (); n++) { // for each package 761 package = packages [n]; // note the package
484 const std::vector<std::string> & aliases = pkgdata->get_package_aliases (packages [n]); // get package aliases 762 break;
485 if (aliases.end () != std::find (aliases.begin (), aliases.end (), alias)) { // if alias is found 763 }
486 package = packages [n]; // note the package 764 }
487 break; 765 }
488 } 766 return package;
489 } 767 }
490 } 768
491 return package; 769 std::string
492 } 770 cdl_exec::resolve_hardware_alias (const std::string alias)
493 771 {
494 std::string cdl_exec::resolve_hardware_alias (const std::string alias) { 772 std::string target = alias;
495 std::string target = alias; 773
496 774 if (! pkgdata->is_known_target (alias)) { // if the alias is not a target name
497 if (! pkgdata->is_known_target (alias)) { // if the alias is not a target name 775 const std::vector<std::string> & targets = pkgdata->get_targets (); // get targets
498 const std::vector<std::string> & targets = pkgdata->get_targets (); // get targets 776 for (unsigned int n = 0; n < targets.size (); n++) { // for each target
499 for (unsigned int n = 0; n < targets.size (); n++) { // for each target 777 const std::vector<std::string> & aliases = pkgdata->get_target_aliases (targets [n]); // get target aliases
500 const std::vector<std::string> & aliases = pkgdata->get_target_aliases (targets [n]); // get target aliases 778 if (aliases.end () != std::find (aliases.begin (), aliases.end (), alias)) { // if alias is found
501 if (aliases.end () != std::find (aliases.begin (), aliases.end (), alias)) { // if alias is found 779 target = targets [n]; // note the target
502 target = targets [n]; // note the target 780 break;
503 break; 781 }
504 } 782 }
505 } 783 }
506 } 784 return target;
507 return target; 785 }
508 }