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

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

Implement the container statement in project file - See CL269 and #4

  • Property svn:eol-style set to native
File size: 46.5 KB
Line 
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"
18#include "cmt_error.h"
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
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)
102{
103 bool result = false;
104
105 release = "";
106 real_name = "";
107
108 cmt_string p = path;
109
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
123 for (;;)
124 {
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
139 cmt_string n;
140
141 CmtSystem::basename (p, n);
142 CmtSystem::dirname (p, p);
143
144 if (n == name)
145 {
146 real_name = name;
147 result = true;
148 break;
149 }
150
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
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
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 */
191Project* ProjectFactory::create_project (const cmt_string& specified_name,
192 const cmt_string& path,
193 const cmt_string& source,
194 Project* parent)
195{
196 cmt_string compressed_path = path;
197 CmtSystem::compress_path (compressed_path);
198 bool specify_name = (specified_name != "");
199
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 }
205
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
213 cmt_string here = CmtSystem::pwd ();
214 if (!CmtSystem::cd (compressed_path)) return (0);
215 cmt_string pwd = CmtSystem::pwd ();
216
217 static Project::ProjectVector& Projects = Project::projects ();
218
219 for (int i = 0; i < Projects.size (); i++)
220 {
221 Project& p = Projects[i];
222
223 if ((p.get_cmtpath () == compressed_path) ||
224 (p.get_cmtpath_pwd () == pwd) ||
225 (specify_name && (p.get_name () == specified_name)))
226 {
227 cmt_string r;
228 cmt_string n;
229
230 get_release_from_path (items, compressed_path, p.get_name (), n, r);
231
232 if (r != p.get_release ())
233 {
234 cerr << "#CMT> Project " << p.get_name ()
235 << " requested with conflicting releases " << p.get_release () << " and " << r << endl;
236 CmtError::set (CmtError::project_release_conflict, p.get_name ());
237 }
238
239 if (parent != 0)
240 {
241 p.add_parent (parent);
242 parent->add_child (&p);
243
244 // Since p is a new parent, we should propagate the settings UP.
245
246 parent->update_strategies_from_children ();
247 }
248
249 CmtSystem::cd (here);
250 return (&p);
251 }
252 }
253
254
255 Project* project = 0;
256 Project* cmt = 0;
257
258 bool is_current = false;
259
260 cmt_string name = specified_name;
261 cmt_string project_name;
262 cmt_string release;
263
264 //
265 // Figure out if this is the current project
266 //
267 if (here.find (pwd) == 0) is_current = true;
268
269 cmt_string text;
270
271 /*
272 Now Figure out the project name from the project file
273 or does not specify the project name
274 */
275 bool has_project_file = false;
276
277 if (CmtSystem::cd ("cmt") && CmtSystem::test_file (Project::get_project_file_name ()))
278 {
279 has_project_file = true;
280 text.read (Project::get_project_file_name ());
281
282 ProjectReader reader;
283
284 reader.run (text);
285
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)
315 {
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 ())
322 {
323 cerr << "#CMT> Warning: project name unspecified in project file." << endl;
324 }
325 */
326
327 get_release_from_path (items, compressed_path, "", name, release);
328
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.
344 /*
345 if (!Cmt::get_quiet ())
346 {
347 cerr << "#CMT> Warning: specified project name "
348 << specified_name
349 << " from the caller does not match path." << endl;
350 }
351 */
352 name = specified_name;
353 }
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 }
367 else
368 {
369 // The specified name is not in the path.
370 /*
371 if (!Cmt::get_quiet ())
372 {
373 cerr << "#CMT> Warning: specified project name "
374 << specified_name
375 << " from project file and from caller does not match path." << endl;
376 }
377 */
378 name = specified_name;
379 }
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 ())
389 {
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 ())
410 {
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;
416 }
417
418 name = specified_name;
419 }
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))
428 {
429 // The specified name has been found from the path.
430 // We believe in the release spec.
431
432 }
433 else
434 {
435 // The specified name is not in the path.
436
437 /*
438 if (!Cmt::get_quiet ())
439 {
440 cerr << "#CMT> Warning: specified project name "
441 << project_name
442 << " from project file does not match path." << endl;
443 }
444 */
445
446 name = project_name;
447 }
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 }
481 else
482 {
483 // The specified name is not in the path.
484 /*
485 if (!Cmt::get_quiet ())
486 {
487 cerr << "#CMT> Warning: specified project name "
488 << specified_name
489 << " from project graph does not match path." << endl;
490 }
491 */
492 name = specified_name;
493 }
494
495 break;
496 }
497 }
498
499 project = Project::add (name, release);
500
501 if (parent != 0)
502 {
503 project->add_parent (parent);
504 parent->add_child (project);
505
506 // Since p is a new parent, we should propagate the settings UP.
507
508 parent->update_strategies_from_children ();
509 }
510
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 {
523 //
524 // The current project defines a tag with its name
525 //
526
527 Tag* tag;
528
529 tag = Tag::add (project->get_name (), PriorityConfig, "PROJECT", 0);
530 tag->mark ();
531 }
532
533 if (text != "")
534 {
535 // Last step is to parse the project file
536
537 SyntaxParser::parse_project_file_text (text,
538 Project::get_project_file_name (),
539 project);
540 }
541
542 CmtSystem::cd (here);
543
544 return (project);
545}
546
547/*----------------------------------------------------------*/
548/* */
549/* Operations on Projects */
550/* */
551/*----------------------------------------------------------*/
552
553//----------------------------------------------------------
554void Project::create (const cmt_string& name,
555 const cmt_string& release,
556 const cmt_string& path)
557{
558 cout << "------------------------------------------" << endl;
559 cout << "Configuring environment for project " << name << " " << release;
560
561 if (path != "")
562 {
563 cout << " in " << path;
564 }
565
566 cout << endl;
567 cout << "CMT version " << Cmt::get_cmt_version () << "." << endl;
568 cout << "------------------------------------------" << endl;
569
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
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//----------------------------------------------------------
715Project* Project::add (const cmt_string& name,
716 const cmt_string& release)
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 {
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
739 Project& p = Projects.add ();
740
741 p.set_name (name);
742 p.set_release (release);
743 p.configure ();
744
745 return (&p);
746
747 //return (project);
748 }
749 }
750
751 Project& project = Projects.add ();
752 project.clear ();
753 project.set_name (name);
754 project.set_release (release);
755 project.configure ();
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{
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
794 Project* current = get_current ();
795
796 if (current != 0) current->show ();
797}
798
799/*----------------------------------------------------------*/
800void Project::show_specified_strategies_for_all ()
801{
802 static ProjectVector& Projects = projects ();
803
804 for (int i = 0; i < Projects.size (); i++)
805 {
806 const Project& project = Projects[i];
807 project.show_specified_strategies ();
808 }
809}
810
811/*----------------------------------------------------------*/
812class VisitorForShowPaths : public IProjectVisitor
813{
814public:
815 VisitorForShowPaths ()
816 {
817 }
818
819 void pre (Project* p)
820 {
821 const cmt_string& w = p->get_cmtpath_pwd ();
822 const cmt_string& s = p->get_cmtpath_source ();
823
824 if (s == "default path") return;
825
826 if (CmtSystem::test_directory (w))
827 {
828 cout << "# Add path " << w << " from " << s << endl;
829 }
830 }
831
832 void in (Project* p)
833 {
834 const cmt_string& w = p->get_cmtpath_pwd ();
835 const cmt_string& s = p->get_cmtpath_source ();
836
837 if (s == "default path") return;
838
839 if (CmtSystem::test_directory (w))
840 {
841 cout << "# Add path " << w << " from " << s << endl;
842 }
843 }
844
845 void post (Project* p)
846 {
847 }
848};
849
850/*----------------------------------------------------------*/
851void Project::show_paths ()
852{
853 VisitorForShowPaths visitor;
854
855 start_visit (visitor);
856}
857
858//----------------------------------------------------------
859const cmt_string& Project::get_project_file_name ()
860{
861 static const cmt_string name = "project.cmt";
862
863 return (name);
864}
865
866//----------------------------------------------------------
867void Project::fill_selection (int depth, CmtSystem::cmt_string_vector& path_selections)
868{
869 static ProjectVector& Projects = projects ();
870
871 for (int i = 0; i < Projects.size (); i++)
872 {
873 Project& project = Projects[i];
874
875 const cmt_string& p = project.get_cmtpath ();
876 const cmt_string& pwd = project.get_cmtpath_pwd ();
877 const cmt_string& src = project.get_cmtpath_source ();
878
879 if (src != "default path")
880 {
881 if (depth > 0)
882 {
883 cmt_string& s1 = path_selections.add ();
884 s1 = p;
885 cmt_string& s2 = path_selections.add ();
886 s2 = pwd;
887 depth--;
888
889 if (depth == 0) break;
890 }
891 }
892 }
893}
894
895//----------------------------------------------------------
896void Project::broadcast (IProjectAction& action)
897{
898 static ProjectVector& Projects = projects ();
899
900 for (int i = 0; i < Projects.size (); i++)
901 {
902 const Project& project = Projects[i];
903
904 if (!action.run (project)) break;
905 }
906}
907
908//----------------------------------------------------------
909void Project::reverse_broadcast (IProjectAction& action)
910{
911 static ProjectVector& Projects = projects ();
912
913 for (int i = (Projects.size () - 1); i >= 0; i--)
914 {
915 const Project& project = Projects[i];
916
917 if (!action.run (project)) break;
918 }
919}
920
921//----------------------------------------------------------
922void Project::scan_paths (PathScanner& scanner, PathScanner::actor& a)
923{
924 static ProjectVector& Projects = projects ();
925
926 for (int i = 0; i < Projects.size (); i++)
927 {
928 const Project& project = Projects[i];
929
930 const cmt_string& p = project.m_cmtpath;
931 scanner.scan_path (p, a);
932 }
933}
934
935//----------------------------------------------------------
936void Project::scan_paths_for_package (PathScanner& scanner, const cmt_string& name)
937{
938 static ProjectVector& Projects = projects ();
939
940 for (int i = 0; i < Projects.size (); i++)
941 {
942 const Project& project = Projects[i];
943
944 const cmt_string& p = project.m_cmtpath;
945 scanner.scan_package (p, name);
946 }
947}
948
949//----------------------------------------------------------
950cmt_string Project::find_in_cmt_paths (const cmt_string& path)
951{
952 const cmt_string pwd = CmtSystem::pwd ();
953
954 static ProjectVector& Projects = projects ();
955
956 for (int i = 0; i < Projects.size (); i++)
957 {
958 const Project& project = Projects[i];
959
960 const cmt_string& p = project.m_cmtpath;
961 const cmt_string& w = project.m_cmtpath_pwd;
962 const cmt_string& s = project.m_cmtpath_source;
963
964 if (s == "default path") continue;
965
966 if (CmtSystem::test_directory (p))
967 {
968 if (path.find (p) != cmt_string::npos)
969 {
970 return (p);
971 }
972
973 // To become the current area, a path must correspond to the current package
974 if (path.find (w) != cmt_string::npos)
975 {
976 return (p);
977 }
978 }
979
980 if (p == w) continue;
981
982 if (CmtSystem::test_directory (w))
983 {
984 if (path.find (w) != cmt_string::npos)
985 {
986 return (w);
987 }
988 }
989 }
990
991 return ("");
992}
993
994//----------------------------------------------------------
995void Project::visit (IProjectVisitor& visitor)
996{
997 if (m_visited) return;
998 m_visited = true;
999
1000 int i;
1001
1002 for (i = 0; i < get_children_size (); i++)
1003 {
1004 Project* child = get_child (i);
1005
1006 if (child->visited ()) continue;
1007
1008 visitor.in (child);
1009 }
1010
1011 for (i = 0; i < m_children.size (); i++)
1012 {
1013 Project* child = m_children[i];
1014 child->visit (visitor);
1015 }
1016}
1017
1018//----------------------------------------------------------
1019void Project::start_visit (IProjectVisitor& visitor)
1020{
1021 static Project::ProjectVector& Projects = Project::projects ();
1022
1023 for (int i = 0; i < Projects.size (); i++)
1024 {
1025 Project& p = Projects[i];
1026 p.m_visited = false;
1027 }
1028
1029 Project* p = get_current ();
1030
1031 if (p == 0) return;
1032
1033 visitor.pre (p);
1034 p->visit (visitor);
1035 visitor.post (p);
1036}
1037
1038//----------------------------------------------------------
1039class VisitorForFillCMTPATH : public IProjectVisitor
1040{
1041public:
1042 VisitorForFillCMTPATH (cmt_string& buffer) : m_buffer (buffer)
1043 {
1044 }
1045
1046 void pre (Project* p)
1047 {
1048 const cmt_string& w = p->get_cmtpath_pwd ();
1049 const cmt_string& s = p->get_cmtpath_source ();
1050
1051 if (s == "default path") return;
1052
1053 if (CmtSystem::test_directory (w))
1054 {
1055 m_buffer += "path_append CMTPATH \"";
1056 m_buffer += w;
1057 m_buffer += "\" \n";
1058 }
1059 }
1060
1061 void in (Project* p)
1062 {
1063 const cmt_string& w = p->get_cmtpath_pwd ();
1064 const cmt_string& s = p->get_cmtpath_source ();
1065
1066 if (s == "default path") return;
1067
1068 if (CmtSystem::test_directory (w))
1069 {
1070 m_buffer += "path_append CMTPATH \"";
1071 m_buffer += w;
1072 m_buffer += "\" \n";
1073 }
1074 }
1075
1076 void post (Project* p)
1077 {
1078 //cerr << "Buffer = " << m_buffer << endl;
1079 }
1080
1081private:
1082 cmt_string& m_buffer;
1083
1084};
1085
1086//----------------------------------------------------------
1087void Project::fill_cmtpaths (cmt_string& buffer)
1088{
1089 /*
1090 Try to re-create all CMTPATH items from project definitions.
1091 The goal is to generate CMTPATH even if this EV was not pre-set
1092 which is the case when CMTPROJECTPATH is only used
1093 */
1094
1095 VisitorForFillCMTPATH visitor (buffer);
1096
1097 start_visit (visitor);
1098}
1099
1100//----------------------------------------------------------
1101Project::Project () : m_name ("")
1102{
1103 clear ();
1104}
1105
1106//----------------------------------------------------------
1107const cmt_string& Project::get_name () const
1108{
1109 return (m_name);
1110}
1111
1112//----------------------------------------------------------
1113const cmt_string& Project::get_release () const
1114{
1115 return (m_release);
1116}
1117
1118//----------------------------------------------------------
1119const cmt_string& Project::get_container () const
1120{
1121 return (m_container);
1122}
1123
1124//----------------------------------------------------------
1125const cmt_string& Project::get_container_version () const
1126{
1127 return (m_container_version);
1128}
1129
1130//----------------------------------------------------------
1131const cmt_string& Project::get_cmtpath () const
1132{
1133 return (m_cmtpath);
1134}
1135
1136//----------------------------------------------------------
1137const cmt_string& Project::get_cmtpath_pwd () const
1138{
1139 return (m_cmtpath_pwd);
1140}
1141
1142//----------------------------------------------------------
1143const cmt_string& Project::get_cmtpath_source () const
1144{
1145 return (m_cmtpath_source);
1146}
1147
1148//----------------------------------------------------------
1149int Project::get_children_size () const
1150{
1151 return (m_children.size ());
1152}
1153
1154//----------------------------------------------------------
1155Project* Project::get_child (int index) const
1156{
1157 if (index < 0) return (0);
1158 if (index >= m_children.size ()) return (0);
1159 return (m_children[index]);
1160}
1161
1162//----------------------------------------------------------
1163bool Project::visited () const
1164{
1165 return (m_visited);
1166}
1167
1168//----------------------------------------------------------
1169void Project::set_name (const cmt_string& name)
1170{
1171 m_name = name;
1172}
1173
1174//----------------------------------------------------------
1175void Project::set_release (const cmt_string& release)
1176{
1177 m_release = release;
1178}
1179
1180//----------------------------------------------------------
1181void Project::set_container (const cmt_string& container)
1182{
1183 m_container = container;
1184}
1185
1186//----------------------------------------------------------
1187void Project::set_container_version (const cmt_string& container_version)
1188{
1189 m_container_version = container_version;
1190}
1191
1192//----------------------------------------------------------
1193void Project::set_cmtpath (const cmt_string& path)
1194{
1195 m_cmtpath = path;
1196}
1197
1198//----------------------------------------------------------
1199void Project::set_cmtpath_pwd (const cmt_string& path)
1200{
1201 m_cmtpath_pwd = path;
1202}
1203
1204//----------------------------------------------------------
1205void Project::set_cmtpath_source (const cmt_string& source)
1206{
1207 m_cmtpath_source = source;
1208}
1209
1210//----------------------------------------------------------
1211void Project::clear ()
1212{
1213 m_name = "";
1214 m_release = "";
1215 m_cmtpath = "";
1216 m_cmtpath_pwd = "";
1217 m_cmtpath_source = "";
1218
1219 m_parents.clear ();
1220 m_children.clear ();
1221
1222 m_configured = false;
1223
1224 m_strategies.clear ();
1225}
1226
1227//----------------------------------------------------------
1228bool Project::has_parent (Project* p) const
1229{
1230 if (p == 0) return (false);
1231 if (p == this) return (false);
1232
1233 const cmt_string& name = p->get_name ();
1234
1235 int i;
1236
1237 for (i = 0; i < m_parents.size (); i++)
1238 {
1239 const Project* parent = m_parents[i];
1240 if (parent == 0) continue;
1241
1242 if (parent->get_name () == name)
1243 {
1244 // registered as a parent
1245 return (true);
1246 }
1247
1248 if (parent->has_parent (p))
1249 {
1250 // recurse
1251 return (true);
1252 }
1253 }
1254
1255 return (false);
1256}
1257
1258//----------------------------------------------------------
1259bool Project::has_child (Project* p) const
1260{
1261 if (p == 0) return (false);
1262 if (p == this) return (false);
1263
1264 const cmt_string& name = p->get_name ();
1265
1266 int i;
1267
1268 for (i = 0; i < m_children.size (); i++)
1269 {
1270 const Project* child = m_children[i];
1271 if (child == 0) continue;
1272
1273 if (child->get_name () == name)
1274 {
1275 // registered as a child
1276 return (true);
1277 }
1278
1279 if (child->has_child (p))
1280 {
1281 // recurse
1282 return (true);
1283 }
1284 }
1285
1286 return (false);
1287}
1288
1289//----------------------------------------------------------
1290void Project::add_parent (Project* p)
1291{
1292 if (p == 0) return;
1293 if (p == this) return;
1294
1295 //cerr << "Adding parent " << p->get_name () << " to " << m_name << endl;
1296
1297 if (has_child (p)) return;
1298 if (has_parent (p)) return;
1299
1300 m_parents.push_back (p);
1301}
1302
1303//----------------------------------------------------------
1304void Project::add_child (Project* p)
1305{
1306 if (p == 0) return;
1307 if (p == this) return;
1308
1309 if (has_child (p)) return;
1310 if (has_parent (p)) return;
1311
1312 m_children.push_back (p);
1313}
1314
1315//----------------------------------------------------------
1316void Project::configure ()
1317{
1318 if (m_configured) return;
1319 m_configured = true;
1320
1321 set_default_strategy ("SetupConfig");
1322 set_default_strategy ("SetupRoot");
1323 set_default_strategy ("SetupCleanup");
1324 set_default_strategy ("BuildPrototypes");
1325 set_default_strategy ("InstallArea");
1326}
1327
1328/**---------------------------------------------------------
1329 A container statement is met in the project file
1330*/
1331void Project::container_action (const cmt_string& name, const cmt_string& version)
1332{
1333 //cerr << "Container action " << name << " " << version << endl;
1334
1335 set_container (name);
1336 set_container_version (version);
1337}
1338
1339/**---------------------------------------------------------
1340 A use statement is met in the project file
1341*/
1342void Project::use_action (const cmt_string& name, const cmt_string& release)
1343{
1344 //cerr << "Use action " << name << " " << release << endl;
1345
1346 // A project with its release is specified
1347 //
1348 // Is this project already visible?
1349 // If not: look for it
1350 // + get CMTPROJECTPATH
1351 // + search from all entries of CMTPROJECTPATH : p(i)/<name>/<release>
1352 // + when found, this should become a new CMTPATH entry
1353 // + the new project is then parsed ... etc...
1354
1355 cmt_string cmtprojectpath = CmtSystem::getenv ("CMTPROJECTPATH");
1356 cmt_string sep;
1357 sep = CmtSystem::path_separator ();
1358
1359 //cerr << "cmtprojectpath = " << cmtprojectpath << endl;
1360 CmtSystem::cmt_string_vector items;
1361 CmtSystem::split (cmtprojectpath, sep, items);
1362
1363 bool found = false;
1364
1365 for (int i = 0; i < items.size (); i++)
1366 {
1367 const cmt_string& item = items[i];
1368 cmt_string p = item;
1369 p += CmtSystem::file_separator ();
1370 p += name;
1371 p += CmtSystem::file_separator ();
1372 p += release;
1373
1374 if (CmtSystem::test_directory (p))
1375 {
1376 //cerr << "Project directory " << p << " exists " << endl;
1377
1378 found = true;
1379
1380 IProjectFactory& factory = ProjectFactory::instance ();
1381
1382 factory.create_project (name, p, "ProjectPath", this);
1383
1384 break;
1385 }
1386 }
1387
1388 if (!found)
1389 {
1390 Project* p = Project::find_by_name (name);
1391
1392 if (p != 0)
1393 {
1394 found = true;
1395
1396 p->add_parent (this);
1397 add_child (p);
1398
1399 update_strategies_from_children ();
1400 }
1401 }
1402
1403 if (!found && (cmtprojectpath != ""))
1404 {
1405 cerr << "#CMT> Project " << name << " " << release << " requested by " << m_name << " not found in CMTPROJECTPATH" << endl;
1406 }
1407}
1408
1409
1410//----------------------------------------------------------
1411Project& Project::operator = (const Project& other)
1412{
1413 m_name = other.m_name;
1414 m_cmtpath = other.m_cmtpath;
1415 m_cmtpath_pwd = other.m_cmtpath_pwd;
1416 m_cmtpath_source = other.m_cmtpath_source;
1417
1418 return (*this);
1419}
1420
1421//----------------------------------------------------------
1422bool Project::operator == (const cmt_string& name) const
1423{
1424 return ((m_name == name));
1425}
1426
1427//----------------------------------------------------------
1428bool Project::operator != (const cmt_string& name) const
1429{
1430 return ((m_name != name));
1431}
1432
1433//----------------------------------------------------------
1434void Project::show ()
1435{
1436 static int level = 0;
1437
1438 bool is_current = false;
1439
1440 cmt_string here = CmtSystem::pwd ();
1441
1442 if (here.find (m_cmtpath) == 0)
1443 {
1444 if (m_cmtpath_source != "default path")
1445 {
1446 is_current = true;
1447 }
1448 }
1449
1450 for (int tab = 0; tab < level; tab++) cout << " ";
1451 cout << m_name << " " << m_release << " (in " << m_cmtpath << ")";
1452
1453 if (is_current) cout << " (current)";
1454
1455 int i;
1456
1457 for (i = 0; i < m_parents.size (); i++)
1458 {
1459 Project* p = m_parents[i];
1460 if (p == 0) continue;
1461 cout << " P=" << p->get_name ();
1462 }
1463
1464 for (i = 0; i < m_children.size (); i++)
1465 {
1466 Project* p = m_children[i];
1467 if (p == 0) continue;
1468 cout << " C=" << p->get_name ();
1469 }
1470
1471 cout << endl;
1472
1473 if (m_visited) return;
1474
1475 m_visited = true;
1476
1477 for (i = 0; i < m_children.size (); i++)
1478 {
1479 Project* p = m_children[i];
1480 if (p == 0) continue;
1481 level++;
1482 p->show ();
1483 level--;
1484 }
1485}
1486
1487
1488//----------------------------------------------------------
1489void Project::show_specified_strategies () const
1490{
1491 int i;
1492
1493 for (i = 0; i < m_strategies.size (); i++)
1494 {
1495 const Strategy& s = m_strategies[i];
1496 if (s.m_specified)
1497 {
1498 const StrategyDef* def = s.m_definition;
1499
1500 cout << "# Project " << m_name
1501 << " sets " << def->m_keyword
1502 << " strategy to " << ((s.m_value) ? def->m_on_value : def->m_off_value);
1503
1504 if (s.m_context != "")
1505 {
1506 cout << " (from package " << s.m_context << ")";
1507 }
1508
1509 cout << endl;
1510 }
1511 }
1512}
1513
1514//----------------------------------------------------------
1515bool Project::has_strategy (const StrategyDef* definition) const
1516{
1517 int i;
1518
1519 for (i = 0; i < m_strategies.size (); i++)
1520 {
1521 const Strategy& s = m_strategies[i];
1522 if (s.m_definition == definition)
1523 {
1524 return (true);
1525 }
1526 }
1527
1528 return (false);
1529}
1530
1531//----------------------------------------------------------
1532bool Project::get_strategy (const cmt_string& name) const
1533{
1534 static StrategyMgr& mgr = StrategyMgr::instance ();
1535
1536 StrategyDef* def = mgr.find_strategy (name);
1537 if (def == 0)
1538 {
1539 cerr << "#CMT> strategy " << name << " undefined" << endl;
1540 return (false);
1541 }
1542
1543 return (get_strategy (def));
1544}
1545
1546//----------------------------------------------------------
1547bool Project::is_specified (const StrategyDef* definition) const
1548{
1549 int i;
1550
1551 for (i = 0; i < m_strategies.size (); i++)
1552 {
1553 Strategy& s = m_strategies[i];
1554 if (s.m_definition == definition)
1555 {
1556 // This strategy is applied in this project
1557 return (s.m_specified);
1558 }
1559 }
1560
1561 // This strategy is not applied in this project
1562 return (false);
1563}
1564
1565//----------------------------------------------------------
1566bool Project::get_strategy (const StrategyDef* def) const
1567{
1568 int i;
1569
1570 for (i = 0; i < m_strategies.size (); i++)
1571 {
1572 Strategy& s = m_strategies[i];
1573 if (s.m_definition == def)
1574 {
1575 // This strategy is applied in this project
1576 if (s.m_specified)
1577 {
1578 return (s.m_specified_value);
1579 }
1580 return (s.m_value);
1581 }
1582 }
1583
1584 // This strategy is not applied in this project
1585 return (def->m_default_value);
1586}
1587
1588//----------------------------------------------------------
1589void Project::set_default_strategy (const cmt_string& name)
1590{
1591 static StrategyMgr& mgr = StrategyMgr::instance ();
1592
1593 StrategyDef* def = mgr.find_strategy (name);
1594 if (def == 0)
1595 {
1596 cerr << "#CMT> strategy " << name << " undefined" << endl;
1597 return;
1598 }
1599
1600 update_strategy (def, def->m_default_value);
1601}
1602
1603
1604//----------------------------------------------------------
1605void Project::set_strategy (const cmt_string& name, const cmt_string& value, const cmt_string& context)
1606{
1607 static StrategyMgr& mgr = StrategyMgr::instance ();
1608
1609 StrategyDef* def = mgr.find_strategy (name);
1610 if (def == 0)
1611 {
1612 cerr << "#CMT> strategy " << name << " undefined" << endl;
1613 return;
1614 }
1615
1616 bool b_value = false;
1617
1618 if (value == def->m_on_value)
1619 {
1620 b_value = true;
1621 }
1622 else if (value == def->m_off_value)
1623 {
1624 b_value = false;
1625 }
1626 else
1627 {
1628 cerr << "#CMT> requested strategy value " << value << " undefined in strategy " << name << endl;
1629 return;
1630 }
1631
1632 set_strategy (def, b_value, context);
1633}
1634
1635//----------------------------------------------------------
1636void Project::set_strategy (StrategyDef* definition, bool b_value, const cmt_string& context)
1637{
1638 bool need_strategy = true;
1639
1640 int i;
1641
1642 for (i = 0; i < m_strategies.size (); i++)
1643 {
1644 Strategy& s = m_strategies[i];
1645 if (s.m_definition == definition)
1646 {
1647 // This strategy is already applied in this project. Let's change it's value
1648 s.set (definition, b_value, get_name ());
1649 if (context != "")
1650 {
1651 if (s.m_context != "") s.m_context += " ";
1652 s.m_context += context;
1653 }
1654 need_strategy = false;
1655 break;
1656 }
1657 }
1658
1659 if (need_strategy)
1660 {
1661 // This strategy is not yet applied in this project.
1662
1663 Strategy& s = m_strategies.add ();
1664 s.clear ();
1665 s.set (definition, b_value, get_name ());
1666 s.m_context = context;
1667 }
1668
1669 for (i = 0; i < m_parents.size (); i++)
1670 {
1671 Project* project = m_parents[i];
1672
1673 project->update_strategy (definition, b_value);
1674 }
1675}
1676
1677/**----------------------------------------------------------
1678 The strategy value is changed because of indirect influences
1679 - default strategy at initialization time
1680 - change in the children
1681 - change in the children list
1682
1683 (This is not a specification : see the set_strategy method)
1684 */
1685void Project::update_strategy (StrategyDef* definition, bool b_value)
1686{
1687 bool need_strategy = true;
1688 bool specified = false;
1689
1690 int i;
1691
1692 for (i = 0; i < m_strategies.size (); i++)
1693 {
1694 Strategy& s = m_strategies[i];
1695 if (s.m_definition == definition)
1696 {
1697 need_strategy = false;
1698
1699 if (!s.m_specified)
1700 {
1701 // This strategy is already applied in this project. Let's change it's value
1702 s.update (definition, b_value, get_name ());
1703 }
1704 else
1705 {
1706 specified = true;
1707 }
1708 break;
1709 }
1710 }
1711
1712 if (need_strategy)
1713 {
1714 // This strategy is not yet applied in this project.
1715
1716 Strategy& s = m_strategies.add ();
1717 s.clear ();
1718 s.update (definition, b_value, get_name ());
1719 }
1720
1721 if (!specified)
1722 {
1723 for (i = 0; i < m_parents.size (); i++)
1724 {
1725 Project* project = m_parents[i];
1726
1727 project->update_strategy (definition, b_value);
1728 }
1729 }
1730}
1731
1732/**----------------------------------------------------------
1733 At least one of the children has changed this strategy
1734 Or the list of children has changed.
1735 We need to update the strategy value accordingly
1736 This will not change the specified value for this strategy
1737 */
1738void Project::update_strategy_from_children (StrategyDef* definition)
1739{
1740 // If this strategy is specified we don't care what happens from the children
1741
1742 //cerr << "Updating strategy " << definition->m_name << " from children for project " << m_name << endl;
1743
1744 int i;
1745
1746 for (i = 0; i < m_strategies.size (); i++)
1747 {
1748 Strategy& s = m_strategies[i];
1749 if (s.m_definition == definition)
1750 {
1751 // This strategy is applied in this project.
1752
1753 if (s.m_specified)
1754 {
1755 // There will be no impact since the strategy is specified
1756
1757 //cerr << "This strategy is specified in this project" << endl;
1758 return;
1759 }
1760
1761 break;
1762 }
1763 }
1764
1765 // The strategy is not specified locally so we will now figure out
1766 // which strategy has to be considered from the mixture of specifications
1767 // from all children.
1768
1769 // Algorithm:
1770 // - We consider children by pairs
1771 // - a child that specifies its strategy wins over a child that does not
1772 // - when the two children have the same level of priority we consider the priority value
1773
1774 Project* selected = 0;
1775 bool selected_is_specified = false;
1776 bool selected_value = definition->m_default_value;
1777
1778 for (i = 0; i < m_children.size (); i++)
1779 {
1780 Project* p = m_children[i];
1781
1782 //cerr << "Checking strategy for child " << p->get_name () << endl;
1783
1784 bool is_specified = p->is_specified (definition);
1785 bool value = p->get_strategy (definition);
1786
1787 if (selected == 0)
1788 {
1789 selected = p;
1790 selected_is_specified = is_specified;
1791 selected_value = value;
1792 continue;
1793 }
1794
1795 if (is_specified == selected_is_specified)
1796 {
1797 if (selected_value != value)
1798 {
1799 // same level of priority but different values -> we must decide
1800 bool priority_value = definition->m_priority_value;
1801 if (value == priority_value)
1802 {
1803 selected = p;
1804 selected_is_specified = is_specified;
1805 selected_value = value;
1806 }
1807 }
1808 }
1809 else
1810 {
1811 if (is_specified)
1812 {
1813 selected = p;
1814 selected_is_specified = is_specified;
1815 selected_value = value;
1816 }
1817 }
1818 }
1819
1820 update_strategy (definition, selected_value);
1821}
1822
1823/**----------------------------------------------------------
1824 At least one of the children has changed its strategies
1825 Or the list of children has changed.
1826 We need to update the strategy values accordingly
1827 This will not change the specified values
1828 */
1829void Project::update_strategies_from_children ()
1830{
1831 StrategyDef::StrategyDefs& defs = StrategyMgr::get_definitions ();
1832
1833 //cerr << "Updating strategies from children for project " << m_name << endl;
1834
1835 int i;
1836
1837 for (i = 0; i < defs.size (); i++)
1838 {
1839 StrategyDef* def = defs[i];
1840
1841 update_strategy_from_children (def);
1842 }
1843
1844 for (i = 0; i < m_parents.size (); i++)
1845 {
1846 Project* p = m_parents[i];
1847 p->update_strategies_from_children ();
1848 }
1849}
1850
1851/**----------------------------------------------------------
1852 The StrategyMgr singleton
1853 */
1854StrategyMgr& StrategyMgr::instance ()
1855{
1856 static StrategyMgr me;
1857 return (me);
1858}
1859
1860/**----------------------------------------------------------
1861 The StrategyMgr constructor
1862 Here are primarily constructed all strategy definitions
1863 */
1864StrategyMgr::StrategyMgr ()
1865{
1866 m_defs.clear ();
1867
1868 StrategyDef* s;
1869
1870 s = new StrategyDef;
1871 s->m_keyword = "build";
1872 s->m_name = "BuildPrototypes";
1873 s->m_on_value = "prototypes";
1874 s->m_off_value = "no_prototypes";
1875 s->m_default_value = true;
1876 s->m_priority_value = false;
1877
1878 m_defs.push_back (s);
1879
1880 s = new StrategyDef;
1881 s->m_keyword = "build";
1882 s->m_name = "InstallArea";
1883 s->m_on_value = "with_installarea";
1884 s->m_off_value = "without_installarea";
1885 s->m_default_value = false;
1886 s->m_priority_value = true;
1887
1888 m_defs.push_back (s);
1889
1890 s = new StrategyDef;
1891 s->m_keyword = "setup";
1892 s->m_name = "SetupConfig";
1893 s->m_on_value = "config";
1894 s->m_off_value = "no_config";
1895 s->m_default_value = true;
1896 s->m_priority_value = false;
1897
1898 m_defs.push_back (s);
1899
1900 s = new StrategyDef;
1901 s->m_keyword = "setup";
1902 s->m_name = "SetupRoot";
1903 s->m_on_value = "root";
1904 s->m_off_value = "no_root";
1905 s->m_default_value = true;
1906 s->m_priority_value = false;
1907
1908 m_defs.push_back (s);
1909
1910 s = new StrategyDef;
1911 s->m_keyword = "setup";
1912 s->m_name = "SetupCleanup";
1913 s->m_on_value = "cleanup";
1914 s->m_off_value = "no_cleanup";
1915 s->m_default_value = true;
1916 s->m_priority_value = false;
1917
1918 m_defs.push_back (s);
1919}
1920
1921/**----------------------------------------------------------
1922 Find a strategy definition by its name
1923 */
1924StrategyDef* StrategyMgr::find_strategy (const cmt_string& name)
1925{
1926 static StrategyMgr& me = instance ();
1927
1928 int i;
1929
1930 for (i = 0; i < me.m_defs.size (); i++)
1931 {
1932 StrategyDef* def = me.m_defs[i];
1933 if (def->m_name == name)
1934 {
1935 return (def);
1936 }
1937 }
1938
1939 return (0);
1940}
1941
1942/**----------------------------------------------------------
1943 Retreive the default value defined for a given strategy
1944 */
1945bool StrategyMgr::get_default_strategy (const cmt_string& name)
1946{
1947 StrategyDef* def = find_strategy (name);
1948 if (def == 0) return (false);
1949 return (def->m_default_value);
1950}
1951
1952/**----------------------------------------------------------
1953 Retreive the priority value defined for a given strategy
1954 This value is used when two children of a project request two conflicting strategy values
1955 */
1956bool StrategyMgr::get_priority_strategy (const cmt_string& name)
1957{
1958 StrategyDef* def = find_strategy (name);
1959 if (def == 0) return (false);
1960 return (def->m_priority_value);
1961}
1962
1963/**----------------------------------------------------------
1964 Return the vector of all existing strategy definitions
1965 */
1966StrategyDef::StrategyDefs& StrategyMgr::get_definitions ()
1967{
1968 static StrategyMgr& me = instance ();
1969
1970 return (me.m_defs);
1971}
1972
1973//-----------------------------------------------------------
1974Strategy::Strategy ()
1975{
1976 clear ();
1977}
1978
1979//-----------------------------------------------------------
1980void Strategy::clear ()
1981{
1982 m_definition = 0;
1983 m_specified = false;
1984 m_specified_value = false;
1985 m_value = false;
1986 m_on_tag = 0;
1987 m_off_tag = 0;
1988}
1989
1990/**----------------------------------------------------------
1991 Specify a new value for this strategy.
1992 This only happens when a strategy statement is met in a project file or in a requirements file.
1993 */
1994void Strategy::set (StrategyDef* definition, bool value, const cmt_string& project_name)
1995{
1996 //cerr << "Setting strategy " << definition->m_name << " for project " << project_name << " to " << value << endl;
1997
1998 m_definition = definition;
1999 m_specified = true;
2000 m_specified_value = value;
2001
2002 update (definition, value, project_name);
2003}
2004
2005/**----------------------------------------------------------
2006 Change the effective value for this strategy.
2007 This has no impact on to the specified value.
2008 This will adapt the tag settings
2009 */
2010void Strategy::update (StrategyDef* definition, bool value, const cmt_string& project_name)
2011{
2012 //cerr << "Updating strategy " << definition->m_name << " for project " << project_name << " to " << value << endl;
2013
2014 m_value = value;
2015 m_definition = definition;
2016
2017 cmt_string to_tag_name = project_name;
2018 cmt_string to_untag_name = project_name;
2019
2020 to_tag_name += "_";
2021 to_untag_name += "_";
2022
2023 if (m_value)
2024 {
2025 to_tag_name += m_definition->m_on_value;
2026 to_untag_name += m_definition->m_off_value;
2027 }
2028 else
2029 {
2030 to_tag_name += m_definition->m_off_value;
2031 to_untag_name += m_definition->m_on_value;
2032 }
2033
2034 m_on_tag = Tag::find (to_tag_name);
2035 m_off_tag = Tag::find (to_untag_name);
2036
2037 if (m_on_tag == 0)
2038 {
2039 m_on_tag = Tag::add (to_tag_name, PriorityConfig, "PROJECT", 0);
2040 m_off_tag = Tag::add (to_untag_name, PriorityConfig, "PROJECT", 0);
2041
2042 m_on_tag->add_tag_exclude (m_off_tag);
2043 m_off_tag->add_tag_exclude (m_on_tag);
2044 }
2045
2046 m_off_tag->unmark ();
2047 m_on_tag->mark ();
2048}
2049
2050const cmt_string& StrategyDef::get_default_value () const
2051{
2052 if (m_default_value)
2053 {
2054 return (m_on_value);
2055 }
2056 else
2057 {
2058 return (m_off_value);
2059 }
2060}
2061
Note: See TracBrowser for help on using the repository browser.