source: CMT/HEAD/source/cmt_project.cxx@ 78

Last change on this file since 78 was 78, checked in by arnault, 20 years ago

Various bug fixes - see CL# 273 274

  • Property svn:eol-style set to native
File size: 46.7 KB
RevLine 
[2]1//-----------------------------------------------------------
2// Copyright Christian Arnault LAL-Orsay CNRS
3// arnault@lal.in2p3.fr
4// See the complete license in cmt_license.txt "http://www.cecill.info".
5//-----------------------------------------------------------
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <ctype.h>
11
12#include "cmt_project.h"
13#include "cmt_database.h"
14#include "cmt_system.h"
15#include "cmt_awk.h"
16#include "cmt_syntax.h"
17#include "cmt_tag.h"
[8]18#include "cmt_error.h"
[2]19
20class ProjectReader : public Awk
21{
22public:
23
24 ProjectReader ()
25 {
26 }
27
28 const cmt_string& get_project_name () const
29 {
30 return (m_project);
31 }
32
33 void filter (const cmt_string& line)
34 {
35 CmtSystem::cmt_string_vector words;
36 CmtSystem::split (line, " \t", words);
37 if (words[0] == "project")
38 {
39 m_project = words[1];
40 }
41 }
42
43private:
44 cmt_string m_project;
45};
46
47class ProjectPatcher : public Awk
48{
49public:
50
51 ProjectPatcher (const cmt_string& p) : m_project (p)
52 {
53 }
54
55 void commit ()
56 {
57 m_output.write (Project::get_project_file_name ());
58 }
59
60 void filter (const cmt_string& line)
61 {
62 if (m_output != "")
63 {
64 m_output += "\n";
65 }
66
67 CmtSystem::cmt_string_vector words;
68 CmtSystem::split (line, " \t", words);
69 if (words[0] == "project")
70 {
71 m_output += "project ";
72 m_output += m_project;
73 }
74 else
75 {
76 m_output += line;
77 }
78 }
79
80private:
81 cmt_string m_output;
82 const cmt_string& m_project;
83};
84
85IProjectFactory& ProjectFactory::instance ()
86{
87 static ProjectFactory me;
88
89 return (me);
90}
91
92void ProjectFactory::reset ()
93{
94 Project::clear_all ();
95}
96
[36]97static bool get_release_from_path (const CmtSystem::cmt_string_vector& items,
98 const cmt_string& path,
99 const cmt_string& name,
100 cmt_string& real_name,
101 cmt_string& release)
[18]102{
103 bool result = false;
104
105 release = "";
[36]106 real_name = "";
[18]107
108 cmt_string p = path;
109
[36]110 if ((items.size () == 0) && (name == ""))
111 {
112 // There is no CMTPROJECTPATH and no expected project name.
113 // We have no way to find a project structure
114 // So we only expect a 2-level structure.
115
116 CmtSystem::basename (p, release);
117 CmtSystem::dirname (p, p);
118 CmtSystem::basename (p, real_name);
119
120 return (false);
121 }
122
[18]123 for (;;)
124 {
[36]125 if (p == "")
126 {
127 // Protection: we found no matching project name
128 // and path was outside any CMTPROJECTPATH
129
130 p = path;
131
132 CmtSystem::basename (p, release);
133 CmtSystem::dirname (p, p);
134 CmtSystem::basename (p, real_name);
135
136 return (false);
137 }
138
[18]139 cmt_string n;
140
141 CmtSystem::basename (p, n);
142 CmtSystem::dirname (p, p);
143
144 if (n == name)
145 {
[36]146 real_name = name;
[18]147 result = true;
148 break;
149 }
150
[36]151 CmtSystem::basename (p, real_name);
152
153 for (int i = 0; i < items.size (); i++)
154 {
155 const cmt_string& item = items[i];
156 if (p == item)
157 {
158 // We have reached an item of CMTPROJECTPATH, no need to continue
159 return (false);
160 }
161 }
162
[18]163 if (release == "")
164 {
165 release = n;
166 }
167 else
168 {
169 cmt_string r;
170
171 r = n;
172 r += CmtSystem::file_separator ();
173 r += release;
174 release = r;
175 }
176 }
177
178 //cerr << "$CMT> GRFP> path=" << path << " name=" << name << " rel=" << release << endl;
179
180 return (result);
181}
182
183
[3]184/*
185 Every new CMTPATH entry becomes associated with a dedicated PROJECT
186 This function will understand this new entry to CMTPATH and understand it:
187 - it can correspond to an existing project (ie already declared)
188 - it's a new project
189 - then it tries to read and parse its project file
190 */
[18]191Project* ProjectFactory::create_project (const cmt_string& specified_name,
192 const cmt_string& path,
[9]193 const cmt_string& source,
194 Project* parent)
[2]195{
196 cmt_string compressed_path = path;
197 CmtSystem::compress_path (compressed_path);
[18]198 bool specify_name = (specified_name != "");
[2]199
[36]200 if (Cmt::get_debug ())
201 {
202 cout << "Creating project " << path << " with parent " << ((parent==0)? "0" : parent->get_name ()) << endl;
203 Project::show_all ();
204 }
[16]205
[36]206 cmt_string sep;
207 sep = CmtSystem::path_separator ();
208
209 cmt_string cmtprojectpath = CmtSystem::getenv ("CMTPROJECTPATH");
210 CmtSystem::cmt_string_vector items;
211 CmtSystem::split (cmtprojectpath, sep, items);
212
[39]213 cmt_string here = CmtSystem::pwd ();
214 if (!CmtSystem::cd (compressed_path)) return (0);
215 cmt_string pwd = CmtSystem::pwd ();
216
[2]217 static Project::ProjectVector& Projects = Project::projects ();
218
219 for (int i = 0; i < Projects.size (); i++)
220 {
221 Project& p = Projects[i];
222
[9]223 if ((p.get_cmtpath () == compressed_path) ||
[39]224 (p.get_cmtpath_pwd () == pwd) ||
[18]225 (specify_name && (p.get_name () == specified_name)))
[9]226 {
[18]227 cmt_string r;
[36]228 cmt_string n;
[18]229
[36]230 get_release_from_path (items, compressed_path, p.get_name (), n, r);
[18]231
232 if (r != p.get_release ())
233 {
[36]234 cerr << "#CMT> Project " << p.get_name ()
235 << " requested with conflicting releases " << p.get_release () << " and " << r << endl;
[18]236 CmtError::set (CmtError::project_release_conflict, p.get_name ());
237 }
238
[9]239 if (parent != 0)
240 {
241 p.add_parent (parent);
242 parent->add_child (&p);
[16]243
244 // Since p is a new parent, we should propagate the settings UP.
245
246 parent->update_strategies_from_children ();
[9]247 }
[16]248
[39]249 CmtSystem::cd (here);
[9]250 return (&p);
251 }
[2]252 }
[18]253
254
[2]255 Project* project = 0;
256 Project* cmt = 0;
257
258 bool is_current = false;
259
[24]260 cmt_string name = specified_name;
[36]261 cmt_string project_name;
[8]262 cmt_string release;
263
[3]264 //
265 // Figure out if this is the current project
266 //
[2]267 if (here.find (pwd) == 0) is_current = true;
268
269 cmt_string text;
270
[3]271 /*
272 Now Figure out the project name from the project file
[15]273 or does not specify the project name
[3]274 */
[36]275 bool has_project_file = false;
276
[2]277 if (CmtSystem::cd ("cmt") && CmtSystem::test_file (Project::get_project_file_name ()))
278 {
[36]279 has_project_file = true;
[2]280 text.read (Project::get_project_file_name ());
281
282 ProjectReader reader;
283
284 reader.run (text);
285
[36]286 project_name = reader.get_project_name ();
287 }
288
289 enum
290 {
291 without_project_file = 0x01,
292 with_project_file = 0x02,
293 without_project_name = 0x04,
294 with_project_name = 0x08,
295 without_specified_name = 0x10,
296 with_specified_name = 0x20,
297 names_mismatch = 0x40,
298 names_match = 0x80
299 };
300
301 int status = ((has_project_file) ? with_project_file : without_project_file) |
302 ((has_project_file && (project_name != "")) ? with_project_name : without_project_name) |
303 ((specify_name) ? with_specified_name : without_specified_name) |
304 ((specify_name && has_project_file && (project_name == specified_name)) ? names_match : names_mismatch);
305
306 if (source == "default path")
307 {
308 name = "CMT";
309 }
310 else
311 {
312 cmt_string n;
313
314 switch (status)
[2]315 {
[36]316 case with_project_file | without_project_name | without_specified_name | names_mismatch:
317
318 // The project is neither specified from the caller nor from the project file
319
320 /*
321 if (!Cmt::get_quiet ())
[18]322 {
[36]323 cerr << "#CMT> Warning: project name unspecified in project file." << endl;
324 }
325 */
326
327 get_release_from_path (items, compressed_path, "", name, release);
[18]328
[36]329 break;
330
331 case with_project_file | without_project_name | with_specified_name | names_mismatch:
332
333 // The name is only specified from the caller
334 // find this specified name in the path
335
336 if (get_release_from_path (items, compressed_path, specified_name, name, release))
337 {
338 // The specified name has been found from the path.
339 // We believe in the release spec.
340 }
341 else
342 {
343 // The specified name is not in the path.
[38]344 /*
[23]345 if (!Cmt::get_quiet ())
346 {
[36]347 cerr << "#CMT> Warning: specified project name "
348 << specified_name
349 << " from the caller does not match path." << endl;
[23]350 }
[38]351 */
352 name = specified_name;
[18]353 }
[36]354
355 break;
356
357 case with_project_file | with_project_name | with_specified_name | names_match:
358
359 // We have a double specification: from the caller and from the project file.
360 // And both specifications are consistent.
361
362 if (get_release_from_path (items, compressed_path, specified_name, name, release))
363 {
364 // The specified name has been found from the path.
365 // We believe in the release spec.
366 }
[18]367 else
368 {
[36]369 // The specified name is not in the path.
[38]370 /*
[36]371 if (!Cmt::get_quiet ())
[18]372 {
[36]373 cerr << "#CMT> Warning: specified project name "
374 << specified_name
375 << " from project file and from caller does not match path." << endl;
[18]376 }
[38]377 */
378 name = specified_name;
[18]379 }
[36]380
381 break;
382
383 case with_project_file | with_project_name | with_specified_name | names_mismatch:
384
385 // We have a double specification: from the caller and from the project file.
386 // Specifications are inconsistent!!
387
388 if (!Cmt::get_quiet ())
[18]389 {
[36]390 cerr << "#CMT> Warning: specified project name "
391 << specified_name
392 << " inconsistent with name "
393 << project_name
394 << " from project file." << endl;
395 }
396
397 if (get_release_from_path (items, compressed_path, specified_name, n, release))
398 {
399 // name from caller wins.
400 }
401 else if (get_release_from_path (items, compressed_path, project_name, name, release))
402 {
403 // name from project file wins.
404 }
405 else
406 {
407 // The specified name is not in the path.
408
409 if (!Cmt::get_quiet ())
[18]410 {
[36]411 cerr << "#CMT> Warning: none of specified project names "
412 << specified_name
413 << " from graph and "
414 << project_name
415 << " from project file match path." << endl;
[18]416 }
[38]417
418 name = specified_name;
[18]419 }
[36]420
421 break;
422
423 case with_project_file | with_project_name | without_specified_name | names_mismatch:
424
425 // Project name is specified in the project file but not from the caller.
426
427 if (get_release_from_path (items, compressed_path, project_name, name, release))
[18]428 {
[36]429 // The specified name has been found from the path.
430 // We believe in the release spec.
[38]431
[36]432 }
433 else
434 {
435 // The specified name is not in the path.
[18]436
[23]437 /*
438 if (!Cmt::get_quiet ())
439 {
[36]440 cerr << "#CMT> Warning: specified project name "
441 << project_name
442 << " from project file does not match path." << endl;
[23]443 }
444 */
[38]445
446 name = project_name;
[18]447 }
[36]448
449 break;
450
451 case without_project_file | without_project_name | without_specified_name | names_mismatch:
452
453 // The project is not specified from the caller and there is no project file
454 // This corresponds to the backward compatibility
455 // For the moment, assume /name/release/ structure where release is one level only
456
457 /*
458 if (!Cmt::get_quiet ())
459 {
460 cerr << "#CMT> Warning: project name is not specified "
461 << " (no project file)." << endl;
462 }
463 */
464
465 CmtSystem::basename (compressed_path, release);
466 CmtSystem::dirname (compressed_path, name);
467 CmtSystem::basename (name, name);
468
469 break;
470
471 case without_project_file | without_project_name | with_specified_name | names_mismatch:
472
473 // The name is only specified from the caller
474 // find this specified name in the path
475
476 if (get_release_from_path (items, compressed_path, specified_name, name, release))
477 {
478 // The specified name has been found from the path.
479 // We believe in the release spec.
480 }
[18]481 else
482 {
[36]483 // The specified name is not in the path.
[38]484 /*
[36]485 if (!Cmt::get_quiet ())
[18]486 {
[36]487 cerr << "#CMT> Warning: specified project name "
488 << specified_name
489 << " from project graph does not match path." << endl;
[18]490 }
[38]491 */
492 name = specified_name;
[18]493 }
[36]494
495 break;
[2]496 }
497 }
498
[8]499 project = Project::add (name, release);
[36]500
[9]501 if (parent != 0)
502 {
503 project->add_parent (parent);
504 parent->add_child (project);
[16]505
506 // Since p is a new parent, we should propagate the settings UP.
507
508 parent->update_strategies_from_children ();
[9]509 }
510
[2]511 if (source == "default path")
512 {
513 cmt = project;
514 is_current = false;
515 }
516
517 project->set_cmtpath (compressed_path);
518 project->set_cmtpath_pwd (pwd);
519 project->set_cmtpath_source (source);
520
521 if (is_current)
522 {
[3]523 //
524 // The current project defines a tag with its name
525 //
526
[2]527 Tag* tag;
528
529 tag = Tag::add (project->get_name (), PriorityConfig, "PROJECT", 0);
530 tag->mark ();
531 }
532
533 if (text != "")
534 {
[3]535 // Last step is to parse the project file
536
[2]537 SyntaxParser::parse_project_file_text (text,
538 Project::get_project_file_name (),
539 project);
540 }
541
542 CmtSystem::cd (here);
[9]543
544 return (project);
[2]545}
546
547/*----------------------------------------------------------*/
548/* */
549/* Operations on Projects */
550/* */
551/*----------------------------------------------------------*/
552
553//----------------------------------------------------------
[22]554void Project::create (const cmt_string& name,
555 const cmt_string& release,
556 const cmt_string& path)
[2]557{
558 cout << "------------------------------------------" << endl;
[22]559 cout << "Configuring environment for project " << name << " " << release;
560
561 if (path != "")
562 {
563 cout << " in " << path;
564 }
565
566 cout << endl;
[2]567 cout << "CMT version " << Cmt::get_cmt_version () << "." << endl;
568 cout << "------------------------------------------" << endl;
569
[22]570 if (path != "")
571 {
572 if (!CmtSystem::mkdir (path))
573 {
574 cout << "Cannot create the " << path << " directory" << endl;
575 return;
576 }
577
578 if (!CmtSystem::cd (path))
579 {
580 cout << "Cannot access the " << path << " directory" << endl;
581 return;
582 }
583 }
584
585 if (!CmtSystem::mkdir (name))
586 {
587 cout << "Cannot create the " << name << " directory" << endl;
588 return;
589 }
590
591 if (!CmtSystem::cd (name))
592 {
593 cout << "Cannot access the " << name << " directory" << endl;
594 return;
595 }
596
597 if (release != "")
598 {
599 if (!CmtSystem::mkdir (release))
600 {
601 cout << "Cannot create the " << release << " directory" << endl;
602 return;
603 }
604
605 if (!CmtSystem::cd (release))
606 {
607 cout << "Cannot access the " << release << " directory" << endl;
608 return;
609 }
610 }
611
[2]612 if (!CmtSystem::test_directory ("cmt"))
613 {
614 if (!CmtSystem::mkdir ("cmt"))
615 {
616 cout << "Cannot create the cmt directory" << endl;
617 return;
618 }
619 else
620 {
621 cout << "Installing the cmt directory" << endl;
622 }
623 }
624
625 CmtSystem::cd ("cmt");
626
627 if (!CmtSystem::test_file (get_project_file_name ()))
628 {
629 cout << "Creating a new project file" << endl;
630
631 ofstream f (get_project_file_name ());
632 if (f)
633 {
634 f << "project " << name << endl;
635 f << endl;
636 f.close ();
637 }
638 }
639 else
640 {
641 cmt_string text;
642 text.read (get_project_file_name ());
643
644 ProjectPatcher p (name);
645
646 p.run (text);
647 p.commit ();
648
649 cout << "project file already there" << endl;
650 }
651}
652
653//----------------------------------------------------------
654Project* Project::find_by_name (const cmt_string& name)
655{
656 static ProjectVector& Projects = projects ();
657
658 for (int i = 0; i < Projects.size (); i++)
659 {
660 Project& p = Projects[i];
661
662 if (p.m_name == name) return (&p);
663 }
664
665 return (0);
666}
667
668//----------------------------------------------------------
669Project* Project::find_by_cmtpath (const cmt_string& cmtpath)
670{
671 cmt_string compressed_path = cmtpath;
672 CmtSystem::compress_path (compressed_path);
673
674 static ProjectVector& Projects = projects ();
675
676 for (int i = 0; i < Projects.size (); i++)
677 {
678 Project& p = Projects[i];
679
680 if (p.m_cmtpath == compressed_path) return (&p);
681 if (p.m_cmtpath_pwd == compressed_path) return (&p);
682 }
683
684 return (0);
685}
686
687//----------------------------------------------------------
688Project* Project::get_current ()
689{
690 cmt_string here = CmtSystem::pwd ();
691
692 static ProjectVector& Projects = projects ();
693
694 Project* result = 0;
695
696 for (int i = (Projects.size () - 1); i >= 0; i--)
697 {
698 Project& p = Projects[i];
699
700 if (here.find (p.m_cmtpath_pwd) == 0)
701 {
702 result = &p;
703 }
704
705 if (here.find (p.m_cmtpath) == 0)
706 {
707 result = &p;
708 }
709 }
710
711 return (result);
712}
713
714//----------------------------------------------------------
[8]715Project* Project::add (const cmt_string& name,
716 const cmt_string& release)
[2]717{
718 static ProjectVector& Projects = projects ();
719
720 //cout << "Project::add> name=" << name << endl;
721
722 {
723 Project* project;
724
725 project = find_by_name (name);
726 if (project != 0)
727 {
[8]728 if (!Cmt::get_quiet ())
729 {
730 if (release != project->get_release ())
731 {
732 cerr << "#CMT> Project " << name << " requested with conflicting releases " << project->get_release () << " and " << release << endl;
733 CmtError::set (CmtError::project_release_conflict, name);
734 }
735 }
736
737 // Project objects are recreated here to follow the hierarchy
738 // This duplication is needed for properly applying the strategies
[2]739 Project& p = Projects.add ();
740
741 p.set_name (name);
[8]742 p.set_release (release);
[10]743 p.configure ();
[2]744
745 return (&p);
[8]746
747 //return (project);
[2]748 }
749 }
750
751 Project& project = Projects.add ();
[16]752 project.clear ();
[2]753 project.set_name (name);
[8]754 project.set_release (release);
[10]755 project.configure ();
[2]756
757 return (&project);
758}
759
760//----------------------------------------------------------
761Project::ProjectVector& Project::projects ()
762{
763 static Database& db = Database::instance ();
764 static ProjectVector& Projects = db.projects ();
765
766 return (Projects);
767}
768
769/*----------------------------------------------------------*/
770void Project::clear_all ()
771{
772 static ProjectVector& Projects = projects ();
773
774 for (int i = 0; i < Projects.size (); i++)
775 {
776 Project& project = Projects[i];
777 project.clear ();
778 }
779
780 Projects.clear ();
781}
782
783/*----------------------------------------------------------*/
784void Project::show_all ()
785{
[9]786 static Project::ProjectVector& Projects = Project::projects ();
787
788 for (int i = 0; i < Projects.size (); i++)
789 {
790 Project& p = Projects[i];
791 p.m_visited = false;
792 }
793
[78]794 Project* p = get_current ();
[9]795
[78]796 if (p == 0)
797 {
798 if (Projects.size () == 0) return;
799
800 p = &(Projects[0]);
801 }
802
803 p->show ();
[2]804}
805
[16]806/*----------------------------------------------------------*/
807void Project::show_specified_strategies_for_all ()
808{
809 static ProjectVector& Projects = projects ();
810
811 for (int i = 0; i < Projects.size (); i++)
812 {
813 const Project& project = Projects[i];
814 project.show_specified_strategies ();
815 }
816}
817
818/*----------------------------------------------------------*/
[9]819class VisitorForShowPaths : public IProjectVisitor
[2]820{
[9]821public:
822 VisitorForShowPaths ()
823 {
824 }
[2]825
[9]826 void pre (Project* p)
827 {
828 const cmt_string& w = p->get_cmtpath_pwd ();
829 const cmt_string& s = p->get_cmtpath_source ();
[2]830
[9]831 if (s == "default path") return;
[2]832
[9]833 if (CmtSystem::test_directory (w))
834 {
835 cout << "# Add path " << w << " from " << s << endl;
836 }
837 }
[2]838
[9]839 void in (Project* p)
840 {
841 const cmt_string& w = p->get_cmtpath_pwd ();
842 const cmt_string& s = p->get_cmtpath_source ();
[2]843
[9]844 if (s == "default path") return;
[2]845
[9]846 if (CmtSystem::test_directory (w))
847 {
848 cout << "# Add path " << w << " from " << s << endl;
849 }
850 }
851
852 void post (Project* p)
853 {
854 }
855};
856
857/*----------------------------------------------------------*/
858void Project::show_paths ()
859{
860 VisitorForShowPaths visitor;
861
862 start_visit (visitor);
[2]863}
864
865//----------------------------------------------------------
866const cmt_string& Project::get_project_file_name ()
867{
868 static const cmt_string name = "project.cmt";
869
870 return (name);
871}
872
873//----------------------------------------------------------
874void Project::fill_selection (int depth, CmtSystem::cmt_string_vector& path_selections)
875{
876 static ProjectVector& Projects = projects ();
877
878 for (int i = 0; i < Projects.size (); i++)
879 {
880 Project& project = Projects[i];
881
882 const cmt_string& p = project.get_cmtpath ();
883 const cmt_string& pwd = project.get_cmtpath_pwd ();
884 const cmt_string& src = project.get_cmtpath_source ();
885
886 if (src != "default path")
887 {
888 if (depth > 0)
889 {
890 cmt_string& s1 = path_selections.add ();
891 s1 = p;
892 cmt_string& s2 = path_selections.add ();
893 s2 = pwd;
894 depth--;
895
896 if (depth == 0) break;
897 }
898 }
899 }
900}
901
902//----------------------------------------------------------
903void Project::broadcast (IProjectAction& action)
904{
905 static ProjectVector& Projects = projects ();
906
907 for (int i = 0; i < Projects.size (); i++)
908 {
909 const Project& project = Projects[i];
910
911 if (!action.run (project)) break;
912 }
913}
914
915//----------------------------------------------------------
916void Project::reverse_broadcast (IProjectAction& action)
917{
918 static ProjectVector& Projects = projects ();
919
920 for (int i = (Projects.size () - 1); i >= 0; i--)
921 {
922 const Project& project = Projects[i];
923
924 if (!action.run (project)) break;
925 }
926}
927
928//----------------------------------------------------------
929void Project::scan_paths (PathScanner& scanner, PathScanner::actor& a)
930{
931 static ProjectVector& Projects = projects ();
932
933 for (int i = 0; i < Projects.size (); i++)
934 {
935 const Project& project = Projects[i];
936
937 const cmt_string& p = project.m_cmtpath;
938 scanner.scan_path (p, a);
939 }
940}
941
942//----------------------------------------------------------
943void Project::scan_paths_for_package (PathScanner& scanner, const cmt_string& name)
944{
945 static ProjectVector& Projects = projects ();
946
947 for (int i = 0; i < Projects.size (); i++)
948 {
949 const Project& project = Projects[i];
950
951 const cmt_string& p = project.m_cmtpath;
952 scanner.scan_package (p, name);
953 }
954}
955
956//----------------------------------------------------------
957cmt_string Project::find_in_cmt_paths (const cmt_string& path)
958{
959 const cmt_string pwd = CmtSystem::pwd ();
960
961 static ProjectVector& Projects = projects ();
962
963 for (int i = 0; i < Projects.size (); i++)
964 {
965 const Project& project = Projects[i];
966
967 const cmt_string& p = project.m_cmtpath;
968 const cmt_string& w = project.m_cmtpath_pwd;
969 const cmt_string& s = project.m_cmtpath_source;
970
971 if (s == "default path") continue;
972
973 if (CmtSystem::test_directory (p))
974 {
975 if (path.find (p) != cmt_string::npos)
976 {
977 return (p);
978 }
979
980 // To become the current area, a path must correspond to the current package
981 if (path.find (w) != cmt_string::npos)
982 {
983 return (p);
984 }
985 }
986
987 if (p == w) continue;
988
989 if (CmtSystem::test_directory (w))
990 {
991 if (path.find (w) != cmt_string::npos)
992 {
993 return (w);
994 }
995 }
996 }
997
998 return ("");
999}
1000
1001//----------------------------------------------------------
[9]1002void Project::visit (IProjectVisitor& visitor)
[3]1003{
[9]1004 if (m_visited) return;
1005 m_visited = true;
[3]1006
[9]1007 int i;
[3]1008
[9]1009 for (i = 0; i < get_children_size (); i++)
[3]1010 {
[9]1011 Project* child = get_child (i);
[3]1012
[9]1013 if (child->visited ()) continue;
[3]1014
[9]1015 visitor.in (child);
1016 }
[3]1017
[9]1018 for (i = 0; i < m_children.size (); i++)
1019 {
1020 Project* child = m_children[i];
1021 child->visit (visitor);
[3]1022 }
1023}
1024
1025//----------------------------------------------------------
[9]1026void Project::start_visit (IProjectVisitor& visitor)
[2]1027{
[9]1028 static Project::ProjectVector& Projects = Project::projects ();
1029
1030 for (int i = 0; i < Projects.size (); i++)
1031 {
1032 Project& p = Projects[i];
1033 p.m_visited = false;
1034 }
1035
1036 Project* p = get_current ();
1037
[78]1038 if (p == 0)
1039 {
1040 if (Projects.size () == 0) return;
[9]1041
[78]1042 p = &(Projects[0]);
1043 }
1044
[9]1045 visitor.pre (p);
1046 p->visit (visitor);
1047 visitor.post (p);
1048}
1049
1050//----------------------------------------------------------
1051class VisitorForFillCMTPATH : public IProjectVisitor
1052{
1053public:
1054 VisitorForFillCMTPATH (cmt_string& buffer) : m_buffer (buffer)
1055 {
[78]1056 buffer = "path CMTPATH \"\" \n";
[9]1057 }
1058
1059 void pre (Project* p)
1060 {
1061 const cmt_string& w = p->get_cmtpath_pwd ();
1062 const cmt_string& s = p->get_cmtpath_source ();
1063
1064 if (s == "default path") return;
1065
1066 if (CmtSystem::test_directory (w))
1067 {
1068 m_buffer += "path_append CMTPATH \"";
1069 m_buffer += w;
[78]1070 m_buffer += ":\" \n";
[9]1071 }
1072 }
1073
1074 void in (Project* p)
1075 {
1076 const cmt_string& w = p->get_cmtpath_pwd ();
1077 const cmt_string& s = p->get_cmtpath_source ();
1078
1079 if (s == "default path") return;
1080
1081 if (CmtSystem::test_directory (w))
1082 {
1083 m_buffer += "path_append CMTPATH \"";
1084 m_buffer += w;
[78]1085 m_buffer += ":\" \n";
[9]1086 }
1087 }
1088
1089 void post (Project* p)
1090 {
1091 //cerr << "Buffer = " << m_buffer << endl;
1092 }
1093
1094private:
1095 cmt_string& m_buffer;
1096
1097};
1098
1099//----------------------------------------------------------
1100void Project::fill_cmtpaths (cmt_string& buffer)
1101{
1102 /*
1103 Try to re-create all CMTPATH items from project definitions.
1104 The goal is to generate CMTPATH even if this EV was not pre-set
1105 which is the case when CMTPROJECTPATH is only used
1106 */
1107
1108 VisitorForFillCMTPATH visitor (buffer);
1109
1110 start_visit (visitor);
1111}
1112
1113//----------------------------------------------------------
1114Project::Project () : m_name ("")
1115{
[2]1116 clear ();
1117}
1118
1119//----------------------------------------------------------
1120const cmt_string& Project::get_name () const
1121{
1122 return (m_name);
1123}
1124
1125//----------------------------------------------------------
[8]1126const cmt_string& Project::get_release () const
1127{
1128 return (m_release);
1129}
1130
1131//----------------------------------------------------------
[41]1132const cmt_string& Project::get_container () const
1133{
1134 return (m_container);
1135}
1136
1137//----------------------------------------------------------
1138const cmt_string& Project::get_container_version () const
1139{
1140 return (m_container_version);
1141}
1142
1143//----------------------------------------------------------
[2]1144const cmt_string& Project::get_cmtpath () const
1145{
1146 return (m_cmtpath);
1147}
1148
1149//----------------------------------------------------------
1150const cmt_string& Project::get_cmtpath_pwd () const
1151{
1152 return (m_cmtpath_pwd);
1153}
1154
1155//----------------------------------------------------------
1156const cmt_string& Project::get_cmtpath_source () const
1157{
1158 return (m_cmtpath_source);
1159}
1160
1161//----------------------------------------------------------
[9]1162int Project::get_children_size () const
1163{
1164 return (m_children.size ());
1165}
1166
1167//----------------------------------------------------------
1168Project* Project::get_child (int index) const
1169{
1170 if (index < 0) return (0);
1171 if (index >= m_children.size ()) return (0);
1172 return (m_children[index]);
1173}
1174
1175//----------------------------------------------------------
1176bool Project::visited () const
1177{
1178 return (m_visited);
1179}
1180
1181//----------------------------------------------------------
[2]1182void Project::set_name (const cmt_string& name)
1183{
1184 m_name = name;
1185}
1186
1187//----------------------------------------------------------
[8]1188void Project::set_release (const cmt_string& release)
1189{
1190 m_release = release;
1191}
1192
1193//----------------------------------------------------------
[41]1194void Project::set_container (const cmt_string& container)
1195{
1196 m_container = container;
1197}
1198
1199//----------------------------------------------------------
1200void Project::set_container_version (const cmt_string& container_version)
1201{
1202 m_container_version = container_version;
1203}
1204
1205//----------------------------------------------------------
[2]1206void Project::set_cmtpath (const cmt_string& path)
1207{
1208 m_cmtpath = path;
1209}
1210
1211//----------------------------------------------------------
1212void Project::set_cmtpath_pwd (const cmt_string& path)
1213{
1214 m_cmtpath_pwd = path;
1215}
1216
1217//----------------------------------------------------------
1218void Project::set_cmtpath_source (const cmt_string& source)
1219{
1220 m_cmtpath_source = source;
1221}
1222
1223//----------------------------------------------------------
1224void Project::clear ()
1225{
1226 m_name = "";
[8]1227 m_release = "";
[2]1228 m_cmtpath = "";
1229 m_cmtpath_pwd = "";
1230 m_cmtpath_source = "";
1231
[9]1232 m_parents.clear ();
1233 m_children.clear ();
1234
[2]1235 m_configured = false;
1236
[15]1237 m_strategies.clear ();
[2]1238}
1239
1240//----------------------------------------------------------
[36]1241bool Project::has_parent (Project* p) const
[9]1242{
[36]1243 if (p == 0) return (false);
1244 if (p == this) return (false);
[9]1245
[36]1246 const cmt_string& name = p->get_name ();
[16]1247
[9]1248 int i;
1249
[36]1250 for (i = 0; i < m_parents.size (); i++)
[9]1251 {
[36]1252 const Project* parent = m_parents[i];
1253 if (parent == 0) continue;
[9]1254
[36]1255 if (parent->get_name () == name)
[9]1256 {
[36]1257 // registered as a parent
1258 return (true);
[9]1259 }
1260
[36]1261 if (parent->has_parent (p))
[9]1262 {
[36]1263 // recurse
1264 return (true);
[9]1265 }
1266 }
1267
[36]1268 return (false);
[9]1269}
1270
1271//----------------------------------------------------------
[36]1272bool Project::has_child (Project* p) const
[9]1273{
[36]1274 if (p == 0) return (false);
1275 if (p == this) return (false);
[9]1276
[36]1277 const cmt_string& name = p->get_name ();
1278
[9]1279 int i;
1280
[36]1281 for (i = 0; i < m_children.size (); i++)
[9]1282 {
[36]1283 const Project* child = m_children[i];
1284 if (child == 0) continue;
[9]1285
[36]1286 if (child->get_name () == name)
[9]1287 {
[36]1288 // registered as a child
1289 return (true);
[9]1290 }
1291
[36]1292 if (child->has_child (p))
[9]1293 {
[36]1294 // recurse
1295 return (true);
[9]1296 }
1297 }
1298
[36]1299 return (false);
1300}
1301
1302//----------------------------------------------------------
1303void Project::add_parent (Project* p)
1304{
1305 if (p == 0) return;
1306 if (p == this) return;
1307
1308 //cerr << "Adding parent " << p->get_name () << " to " << m_name << endl;
1309
1310 if (has_child (p)) return;
1311 if (has_parent (p)) return;
1312
1313 m_parents.push_back (p);
1314}
1315
1316//----------------------------------------------------------
1317void Project::add_child (Project* p)
1318{
1319 if (p == 0) return;
1320 if (p == this) return;
1321
1322 if (has_child (p)) return;
1323 if (has_parent (p)) return;
1324
[9]1325 m_children.push_back (p);
1326}
1327
1328//----------------------------------------------------------
[2]1329void Project::configure ()
1330{
1331 if (m_configured) return;
1332 m_configured = true;
1333
[15]1334 set_default_strategy ("SetupConfig");
1335 set_default_strategy ("SetupRoot");
1336 set_default_strategy ("SetupCleanup");
1337 set_default_strategy ("BuildPrototypes");
1338 set_default_strategy ("InstallArea");
[2]1339}
1340
[15]1341/**---------------------------------------------------------
[41]1342 A container statement is met in the project file
1343*/
1344void Project::container_action (const cmt_string& name, const cmt_string& version)
1345{
1346 //cerr << "Container action " << name << " " << version << endl;
1347
1348 set_container (name);
1349 set_container_version (version);
1350}
1351
1352/**---------------------------------------------------------
[15]1353 A use statement is met in the project file
1354*/
[3]1355void Project::use_action (const cmt_string& name, const cmt_string& release)
1356{
1357 //cerr << "Use action " << name << " " << release << endl;
1358
1359 // A project with its release is specified
1360 //
1361 // Is this project already visible?
1362 // If not: look for it
1363 // + get CMTPROJECTPATH
[15]1364 // + search from all entries of CMTPROJECTPATH : p(i)/<name>/<release>
[3]1365 // + when found, this should become a new CMTPATH entry
1366 // + the new project is then parsed ... etc...
1367
1368 cmt_string cmtprojectpath = CmtSystem::getenv ("CMTPROJECTPATH");
1369 cmt_string sep;
[15]1370 sep = CmtSystem::path_separator ();
[3]1371
1372 //cerr << "cmtprojectpath = " << cmtprojectpath << endl;
1373 CmtSystem::cmt_string_vector items;
1374 CmtSystem::split (cmtprojectpath, sep, items);
[16]1375
1376 bool found = false;
1377
[3]1378 for (int i = 0; i < items.size (); i++)
1379 {
1380 const cmt_string& item = items[i];
1381 cmt_string p = item;
1382 p += CmtSystem::file_separator ();
1383 p += name;
1384 p += CmtSystem::file_separator ();
1385 p += release;
1386
1387 if (CmtSystem::test_directory (p))
1388 {
[15]1389 //cerr << "Project directory " << p << " exists " << endl;
[3]1390
[16]1391 found = true;
1392
[3]1393 IProjectFactory& factory = ProjectFactory::instance ();
1394
[18]1395 factory.create_project (name, p, "ProjectPath", this);
[3]1396
1397 break;
1398 }
1399 }
[16]1400
1401 if (!found)
1402 {
1403 Project* p = Project::find_by_name (name);
1404
1405 if (p != 0)
1406 {
1407 found = true;
1408
1409 p->add_parent (this);
1410 add_child (p);
1411
1412 update_strategies_from_children ();
1413 }
1414 }
1415
1416 if (!found && (cmtprojectpath != ""))
1417 {
1418 cerr << "#CMT> Project " << name << " " << release << " requested by " << m_name << " not found in CMTPROJECTPATH" << endl;
1419 }
[3]1420}
1421
1422
1423//----------------------------------------------------------
[2]1424Project& Project::operator = (const Project& other)
1425{
1426 m_name = other.m_name;
1427 m_cmtpath = other.m_cmtpath;
1428 m_cmtpath_pwd = other.m_cmtpath_pwd;
1429 m_cmtpath_source = other.m_cmtpath_source;
1430
1431 return (*this);
1432}
1433
1434//----------------------------------------------------------
1435bool Project::operator == (const cmt_string& name) const
1436{
1437 return ((m_name == name));
1438}
1439
1440//----------------------------------------------------------
1441bool Project::operator != (const cmt_string& name) const
1442{
1443 return ((m_name != name));
1444}
1445
1446//----------------------------------------------------------
[9]1447void Project::show ()
[2]1448{
[9]1449 static int level = 0;
1450
[2]1451 bool is_current = false;
1452
1453 cmt_string here = CmtSystem::pwd ();
1454
1455 if (here.find (m_cmtpath) == 0)
1456 {
1457 if (m_cmtpath_source != "default path")
1458 {
1459 is_current = true;
1460 }
1461 }
1462
[9]1463 for (int tab = 0; tab < level; tab++) cout << " ";
[8]1464 cout << m_name << " " << m_release << " (in " << m_cmtpath << ")";
[2]1465
1466 if (is_current) cout << " (current)";
1467
[9]1468 int i;
1469
1470 for (i = 0; i < m_parents.size (); i++)
1471 {
1472 Project* p = m_parents[i];
1473 if (p == 0) continue;
1474 cout << " P=" << p->get_name ();
1475 }
1476
1477 for (i = 0; i < m_children.size (); i++)
1478 {
1479 Project* p = m_children[i];
1480 if (p == 0) continue;
1481 cout << " C=" << p->get_name ();
1482 }
1483
[2]1484 cout << endl;
[9]1485
1486 if (m_visited) return;
1487
1488 m_visited = true;
1489
1490 for (i = 0; i < m_children.size (); i++)
1491 {
1492 Project* p = m_children[i];
1493 if (p == 0) continue;
1494 level++;
1495 p->show ();
1496 level--;
1497 }
[2]1498}
1499
1500
1501//----------------------------------------------------------
[16]1502void Project::show_specified_strategies () const
[2]1503{
[16]1504 int i;
1505
1506 for (i = 0; i < m_strategies.size (); i++)
1507 {
1508 const Strategy& s = m_strategies[i];
1509 if (s.m_specified)
1510 {
1511 const StrategyDef* def = s.m_definition;
1512
1513 cout << "# Project " << m_name
1514 << " sets " << def->m_keyword
1515 << " strategy to " << ((s.m_value) ? def->m_on_value : def->m_off_value);
1516
1517 if (s.m_context != "")
1518 {
1519 cout << " (from package " << s.m_context << ")";
1520 }
1521
1522 cout << endl;
1523 }
1524 }
[2]1525}
1526
1527//----------------------------------------------------------
[15]1528bool Project::has_strategy (const StrategyDef* definition) const
[2]1529{
[10]1530 int i;
1531
[15]1532 for (i = 0; i < m_strategies.size (); i++)
[10]1533 {
[15]1534 const Strategy& s = m_strategies[i];
1535 if (s.m_definition == definition)
[10]1536 {
[15]1537 return (true);
[10]1538 }
[15]1539 }
[10]1540
[15]1541 return (false);
1542}
[10]1543
[15]1544//----------------------------------------------------------
1545bool Project::get_strategy (const cmt_string& name) const
1546{
1547 static StrategyMgr& mgr = StrategyMgr::instance ();
[10]1548
[15]1549 StrategyDef* def = mgr.find_strategy (name);
1550 if (def == 0)
[2]1551 {
[15]1552 cerr << "#CMT> strategy " << name << " undefined" << endl;
1553 return (false);
[2]1554 }
[15]1555
1556 return (get_strategy (def));
1557}
1558
1559//----------------------------------------------------------
1560bool Project::is_specified (const StrategyDef* definition) const
1561{
1562 int i;
1563
1564 for (i = 0; i < m_strategies.size (); i++)
[10]1565 {
[15]1566 Strategy& s = m_strategies[i];
1567 if (s.m_definition == definition)
[10]1568 {
[15]1569 // This strategy is applied in this project
1570 return (s.m_specified);
[10]1571 }
[15]1572 }
[2]1573
[15]1574 // This strategy is not applied in this project
1575 return (false);
1576}
1577
1578//----------------------------------------------------------
1579bool Project::get_strategy (const StrategyDef* def) const
1580{
1581 int i;
1582
1583 for (i = 0; i < m_strategies.size (); i++)
1584 {
1585 Strategy& s = m_strategies[i];
1586 if (s.m_definition == def)
[10]1587 {
[15]1588 // This strategy is applied in this project
1589 if (s.m_specified)
1590 {
1591 return (s.m_specified_value);
1592 }
1593 return (s.m_value);
[10]1594 }
1595 }
1596
[15]1597 // This strategy is not applied in this project
1598 return (def->m_default_value);
[2]1599}
1600
1601//----------------------------------------------------------
[15]1602void Project::set_default_strategy (const cmt_string& name)
[2]1603{
[15]1604 static StrategyMgr& mgr = StrategyMgr::instance ();
[2]1605
[15]1606 StrategyDef* def = mgr.find_strategy (name);
1607 if (def == 0)
1608 {
1609 cerr << "#CMT> strategy " << name << " undefined" << endl;
1610 return;
1611 }
[2]1612
[15]1613 update_strategy (def, def->m_default_value);
1614}
[9]1615
[15]1616
1617//----------------------------------------------------------
[16]1618void Project::set_strategy (const cmt_string& name, const cmt_string& value, const cmt_string& context)
[15]1619{
1620 static StrategyMgr& mgr = StrategyMgr::instance ();
1621
1622 StrategyDef* def = mgr.find_strategy (name);
1623 if (def == 0)
[2]1624 {
[15]1625 cerr << "#CMT> strategy " << name << " undefined" << endl;
1626 return;
[2]1627 }
1628
[15]1629 bool b_value = false;
1630
1631 if (value == def->m_on_value)
1632 {
1633 b_value = true;
1634 }
1635 else if (value == def->m_off_value)
1636 {
1637 b_value = false;
1638 }
1639 else
1640 {
1641 cerr << "#CMT> requested strategy value " << value << " undefined in strategy " << name << endl;
1642 return;
1643 }
1644
[16]1645 set_strategy (def, b_value, context);
[2]1646}
1647
1648//----------------------------------------------------------
[16]1649void Project::set_strategy (StrategyDef* definition, bool b_value, const cmt_string& context)
[2]1650{
[15]1651 bool need_strategy = true;
[2]1652
[15]1653 int i;
[2]1654
[15]1655 for (i = 0; i < m_strategies.size (); i++)
1656 {
1657 Strategy& s = m_strategies[i];
1658 if (s.m_definition == definition)
1659 {
1660 // This strategy is already applied in this project. Let's change it's value
1661 s.set (definition, b_value, get_name ());
[16]1662 if (context != "")
1663 {
1664 if (s.m_context != "") s.m_context += " ";
1665 s.m_context += context;
1666 }
[15]1667 need_strategy = false;
1668 break;
1669 }
1670 }
[2]1671
[15]1672 if (need_strategy)
[2]1673 {
[15]1674 // This strategy is not yet applied in this project.
1675
1676 Strategy& s = m_strategies.add ();
[16]1677 s.clear ();
[15]1678 s.set (definition, b_value, get_name ());
[16]1679 s.m_context = context;
[2]1680 }
[15]1681
1682 for (i = 0; i < m_parents.size (); i++)
1683 {
1684 Project* project = m_parents[i];
[2]1685
[15]1686 project->update_strategy (definition, b_value);
1687 }
1688}
[2]1689
[15]1690/**----------------------------------------------------------
1691 The strategy value is changed because of indirect influences
1692 - default strategy at initialization time
1693 - change in the children
1694 - change in the children list
1695
1696 (This is not a specification : see the set_strategy method)
1697 */
1698void Project::update_strategy (StrategyDef* definition, bool b_value)
1699{
1700 bool need_strategy = true;
[16]1701 bool specified = false;
[15]1702
1703 int i;
1704
1705 for (i = 0; i < m_strategies.size (); i++)
[2]1706 {
[15]1707 Strategy& s = m_strategies[i];
1708 if (s.m_definition == definition)
1709 {
1710 need_strategy = false;
[16]1711
1712 if (!s.m_specified)
1713 {
1714 // This strategy is already applied in this project. Let's change it's value
1715 s.update (definition, b_value, get_name ());
1716 }
1717 else
1718 {
1719 specified = true;
1720 }
[15]1721 break;
1722 }
[2]1723 }
1724
[15]1725 if (need_strategy)
[2]1726 {
[15]1727 // This strategy is not yet applied in this project.
1728
1729 Strategy& s = m_strategies.add ();
[16]1730 s.clear ();
[15]1731 s.update (definition, b_value, get_name ());
[2]1732 }
[16]1733
1734 if (!specified)
[2]1735 {
[16]1736 for (i = 0; i < m_parents.size (); i++)
1737 {
1738 Project* project = m_parents[i];
[2]1739
[15]1740 project->update_strategy (definition, b_value);
[2]1741 }
1742 }
1743}
1744
[15]1745/**----------------------------------------------------------
1746 At least one of the children has changed this strategy
1747 Or the list of children has changed.
1748 We need to update the strategy value accordingly
1749 This will not change the specified value for this strategy
1750 */
1751void Project::update_strategy_from_children (StrategyDef* definition)
[2]1752{
[15]1753 // If this strategy is specified we don't care what happens from the children
[2]1754
[16]1755 //cerr << "Updating strategy " << definition->m_name << " from children for project " << m_name << endl;
[2]1756
[15]1757 int i;
[2]1758
[15]1759 for (i = 0; i < m_strategies.size (); i++)
[2]1760 {
[15]1761 Strategy& s = m_strategies[i];
1762 if (s.m_definition == definition)
1763 {
1764 // This strategy is applied in this project.
1765
1766 if (s.m_specified)
1767 {
1768 // There will be no impact since the strategy is specified
1769
[16]1770 //cerr << "This strategy is specified in this project" << endl;
[15]1771 return;
1772 }
1773
1774 break;
1775 }
[2]1776 }
1777
[15]1778 // The strategy is not specified locally so we will now figure out
1779 // which strategy has to be considered from the mixture of specifications
1780 // from all children.
[2]1781
[15]1782 // Algorithm:
1783 // - We consider children by pairs
1784 // - a child that specifies its strategy wins over a child that does not
1785 // - when the two children have the same level of priority we consider the priority value
1786
1787 Project* selected = 0;
1788 bool selected_is_specified = false;
[16]1789 bool selected_value = definition->m_default_value;
[15]1790
1791 for (i = 0; i < m_children.size (); i++)
[2]1792 {
[15]1793 Project* p = m_children[i];
1794
[16]1795 //cerr << "Checking strategy for child " << p->get_name () << endl;
[15]1796
1797 bool is_specified = p->is_specified (definition);
1798 bool value = p->get_strategy (definition);
1799
1800 if (selected == 0)
1801 {
1802 selected = p;
1803 selected_is_specified = is_specified;
1804 selected_value = value;
1805 continue;
1806 }
1807
1808 if (is_specified == selected_is_specified)
1809 {
1810 if (selected_value != value)
1811 {
1812 // same level of priority but different values -> we must decide
1813 bool priority_value = definition->m_priority_value;
1814 if (value == priority_value)
1815 {
1816 selected = p;
1817 selected_is_specified = is_specified;
1818 selected_value = value;
1819 }
1820 }
1821 }
1822 else
1823 {
1824 if (is_specified)
1825 {
1826 selected = p;
1827 selected_is_specified = is_specified;
1828 selected_value = value;
1829 }
1830 }
[2]1831 }
1832
[15]1833 update_strategy (definition, selected_value);
1834}
1835
1836/**----------------------------------------------------------
1837 At least one of the children has changed its strategies
1838 Or the list of children has changed.
1839 We need to update the strategy values accordingly
1840 This will not change the specified values
1841 */
1842void Project::update_strategies_from_children ()
1843{
1844 StrategyDef::StrategyDefs& defs = StrategyMgr::get_definitions ();
1845
[16]1846 //cerr << "Updating strategies from children for project " << m_name << endl;
[15]1847
1848 int i;
1849
1850 for (i = 0; i < defs.size (); i++)
[2]1851 {
[15]1852 StrategyDef* def = defs[i];
[16]1853
[15]1854 update_strategy_from_children (def);
[2]1855 }
[16]1856
1857 for (i = 0; i < m_parents.size (); i++)
1858 {
1859 Project* p = m_parents[i];
1860 p->update_strategies_from_children ();
1861 }
[15]1862}
1863
1864/**----------------------------------------------------------
1865 The StrategyMgr singleton
1866 */
1867StrategyMgr& StrategyMgr::instance ()
1868{
1869 static StrategyMgr me;
1870 return (me);
1871}
1872
1873/**----------------------------------------------------------
1874 The StrategyMgr constructor
1875 Here are primarily constructed all strategy definitions
1876 */
1877StrategyMgr::StrategyMgr ()
1878{
1879 m_defs.clear ();
1880
1881 StrategyDef* s;
1882
1883 s = new StrategyDef;
[16]1884 s->m_keyword = "build";
[15]1885 s->m_name = "BuildPrototypes";
1886 s->m_on_value = "prototypes";
1887 s->m_off_value = "no_prototypes";
1888 s->m_default_value = true;
1889 s->m_priority_value = false;
1890
1891 m_defs.push_back (s);
1892
1893 s = new StrategyDef;
[16]1894 s->m_keyword = "build";
[15]1895 s->m_name = "InstallArea";
1896 s->m_on_value = "with_installarea";
1897 s->m_off_value = "without_installarea";
1898 s->m_default_value = false;
1899 s->m_priority_value = true;
1900
1901 m_defs.push_back (s);
1902
1903 s = new StrategyDef;
[16]1904 s->m_keyword = "setup";
[15]1905 s->m_name = "SetupConfig";
1906 s->m_on_value = "config";
1907 s->m_off_value = "no_config";
1908 s->m_default_value = true;
1909 s->m_priority_value = false;
1910
1911 m_defs.push_back (s);
1912
1913 s = new StrategyDef;
[16]1914 s->m_keyword = "setup";
[15]1915 s->m_name = "SetupRoot";
1916 s->m_on_value = "root";
1917 s->m_off_value = "no_root";
1918 s->m_default_value = true;
1919 s->m_priority_value = false;
1920
1921 m_defs.push_back (s);
1922
1923 s = new StrategyDef;
[16]1924 s->m_keyword = "setup";
[15]1925 s->m_name = "SetupCleanup";
1926 s->m_on_value = "cleanup";
1927 s->m_off_value = "no_cleanup";
1928 s->m_default_value = true;
1929 s->m_priority_value = false;
1930
1931 m_defs.push_back (s);
1932}
1933
1934/**----------------------------------------------------------
1935 Find a strategy definition by its name
1936 */
1937StrategyDef* StrategyMgr::find_strategy (const cmt_string& name)
1938{
1939 static StrategyMgr& me = instance ();
1940
1941 int i;
1942
1943 for (i = 0; i < me.m_defs.size (); i++)
[2]1944 {
[15]1945 StrategyDef* def = me.m_defs[i];
1946 if (def->m_name == name)
[2]1947 {
[15]1948 return (def);
[2]1949 }
1950 }
[15]1951
1952 return (0);
[2]1953}
1954
[15]1955/**----------------------------------------------------------
1956 Retreive the default value defined for a given strategy
1957 */
1958bool StrategyMgr::get_default_strategy (const cmt_string& name)
1959{
1960 StrategyDef* def = find_strategy (name);
1961 if (def == 0) return (false);
1962 return (def->m_default_value);
1963}
1964
1965/**----------------------------------------------------------
1966 Retreive the priority value defined for a given strategy
1967 This value is used when two children of a project request two conflicting strategy values
1968 */
1969bool StrategyMgr::get_priority_strategy (const cmt_string& name)
1970{
1971 StrategyDef* def = find_strategy (name);
1972 if (def == 0) return (false);
1973 return (def->m_priority_value);
1974}
1975
1976/**----------------------------------------------------------
1977 Return the vector of all existing strategy definitions
1978 */
1979StrategyDef::StrategyDefs& StrategyMgr::get_definitions ()
1980{
1981 static StrategyMgr& me = instance ();
1982
1983 return (me.m_defs);
1984}
1985
[16]1986//-----------------------------------------------------------
1987Strategy::Strategy ()
1988{
1989 clear ();
1990}
1991
1992//-----------------------------------------------------------
1993void Strategy::clear ()
1994{
1995 m_definition = 0;
1996 m_specified = false;
1997 m_specified_value = false;
1998 m_value = false;
1999 m_on_tag = 0;
2000 m_off_tag = 0;
2001}
2002
[15]2003/**----------------------------------------------------------
2004 Specify a new value for this strategy.
2005 This only happens when a strategy statement is met in a project file or in a requirements file.
2006 */
2007void Strategy::set (StrategyDef* definition, bool value, const cmt_string& project_name)
2008{
[16]2009 //cerr << "Setting strategy " << definition->m_name << " for project " << project_name << " to " << value << endl;
2010
[15]2011 m_definition = definition;
2012 m_specified = true;
2013 m_specified_value = value;
2014
2015 update (definition, value, project_name);
2016}
2017
2018/**----------------------------------------------------------
2019 Change the effective value for this strategy.
2020 This has no impact on to the specified value.
2021 This will adapt the tag settings
2022 */
2023void Strategy::update (StrategyDef* definition, bool value, const cmt_string& project_name)
2024{
[16]2025 //cerr << "Updating strategy " << definition->m_name << " for project " << project_name << " to " << value << endl;
2026
[15]2027 m_value = value;
[16]2028 m_definition = definition;
[15]2029
2030 cmt_string to_tag_name = project_name;
2031 cmt_string to_untag_name = project_name;
2032
2033 to_tag_name += "_";
2034 to_untag_name += "_";
2035
2036 if (m_value)
2037 {
2038 to_tag_name += m_definition->m_on_value;
2039 to_untag_name += m_definition->m_off_value;
2040 }
2041 else
2042 {
2043 to_tag_name += m_definition->m_off_value;
2044 to_untag_name += m_definition->m_on_value;
2045 }
2046
2047 m_on_tag = Tag::find (to_tag_name);
2048 m_off_tag = Tag::find (to_untag_name);
2049
2050 if (m_on_tag == 0)
2051 {
2052 m_on_tag = Tag::add (to_tag_name, PriorityConfig, "PROJECT", 0);
2053 m_off_tag = Tag::add (to_untag_name, PriorityConfig, "PROJECT", 0);
2054
2055 m_on_tag->add_tag_exclude (m_off_tag);
2056 m_off_tag->add_tag_exclude (m_on_tag);
2057 }
2058
2059 m_off_tag->unmark ();
2060 m_on_tag->mark ();
2061}
2062
2063const cmt_string& StrategyDef::get_default_value () const
2064{
2065 if (m_default_value)
2066 {
2067 return (m_on_value);
2068 }
2069 else
2070 {
2071 return (m_off_value);
2072 }
2073}
2074
Note: See TracBrowser for help on using the repository browser.