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

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

Fix PATH symbols management with symlinks - See CL 268

  • Property svn:eol-style set to native
File size: 45.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_cmtpath () const
1120{
1121 return (m_cmtpath);
1122}
1123
1124//----------------------------------------------------------
1125const cmt_string& Project::get_cmtpath_pwd () const
1126{
1127 return (m_cmtpath_pwd);
1128}
1129
1130//----------------------------------------------------------
1131const cmt_string& Project::get_cmtpath_source () const
1132{
1133 return (m_cmtpath_source);
1134}
1135
1136//----------------------------------------------------------
1137int Project::get_children_size () const
1138{
1139 return (m_children.size ());
1140}
1141
1142//----------------------------------------------------------
1143Project* Project::get_child (int index) const
1144{
1145 if (index < 0) return (0);
1146 if (index >= m_children.size ()) return (0);
1147 return (m_children[index]);
1148}
1149
1150//----------------------------------------------------------
1151bool Project::visited () const
1152{
1153 return (m_visited);
1154}
1155
1156//----------------------------------------------------------
1157void Project::set_name (const cmt_string& name)
1158{
1159 m_name = name;
1160}
1161
1162//----------------------------------------------------------
1163void Project::set_release (const cmt_string& release)
1164{
1165 m_release = release;
1166}
1167
1168//----------------------------------------------------------
1169void Project::set_cmtpath (const cmt_string& path)
1170{
1171 m_cmtpath = path;
1172}
1173
1174//----------------------------------------------------------
1175void Project::set_cmtpath_pwd (const cmt_string& path)
1176{
1177 m_cmtpath_pwd = path;
1178}
1179
1180//----------------------------------------------------------
1181void Project::set_cmtpath_source (const cmt_string& source)
1182{
1183 m_cmtpath_source = source;
1184}
1185
1186//----------------------------------------------------------
1187void Project::clear ()
1188{
1189 m_name = "";
1190 m_release = "";
1191 m_cmtpath = "";
1192 m_cmtpath_pwd = "";
1193 m_cmtpath_source = "";
1194
1195 m_parents.clear ();
1196 m_children.clear ();
1197
1198 m_configured = false;
1199
1200 m_strategies.clear ();
1201}
1202
1203//----------------------------------------------------------
1204bool Project::has_parent (Project* p) const
1205{
1206 if (p == 0) return (false);
1207 if (p == this) return (false);
1208
1209 const cmt_string& name = p->get_name ();
1210
1211 int i;
1212
1213 for (i = 0; i < m_parents.size (); i++)
1214 {
1215 const Project* parent = m_parents[i];
1216 if (parent == 0) continue;
1217
1218 if (parent->get_name () == name)
1219 {
1220 // registered as a parent
1221 return (true);
1222 }
1223
1224 if (parent->has_parent (p))
1225 {
1226 // recurse
1227 return (true);
1228 }
1229 }
1230
1231 return (false);
1232}
1233
1234//----------------------------------------------------------
1235bool Project::has_child (Project* p) const
1236{
1237 if (p == 0) return (false);
1238 if (p == this) return (false);
1239
1240 const cmt_string& name = p->get_name ();
1241
1242 int i;
1243
1244 for (i = 0; i < m_children.size (); i++)
1245 {
1246 const Project* child = m_children[i];
1247 if (child == 0) continue;
1248
1249 if (child->get_name () == name)
1250 {
1251 // registered as a child
1252 return (true);
1253 }
1254
1255 if (child->has_child (p))
1256 {
1257 // recurse
1258 return (true);
1259 }
1260 }
1261
1262 return (false);
1263}
1264
1265//----------------------------------------------------------
1266void Project::add_parent (Project* p)
1267{
1268 if (p == 0) return;
1269 if (p == this) return;
1270
1271 //cerr << "Adding parent " << p->get_name () << " to " << m_name << endl;
1272
1273 if (has_child (p)) return;
1274 if (has_parent (p)) return;
1275
1276 m_parents.push_back (p);
1277}
1278
1279//----------------------------------------------------------
1280void Project::add_child (Project* p)
1281{
1282 if (p == 0) return;
1283 if (p == this) return;
1284
1285 if (has_child (p)) return;
1286 if (has_parent (p)) return;
1287
1288 m_children.push_back (p);
1289}
1290
1291//----------------------------------------------------------
1292void Project::configure ()
1293{
1294 if (m_configured) return;
1295 m_configured = true;
1296
1297 set_default_strategy ("SetupConfig");
1298 set_default_strategy ("SetupRoot");
1299 set_default_strategy ("SetupCleanup");
1300 set_default_strategy ("BuildPrototypes");
1301 set_default_strategy ("InstallArea");
1302}
1303
1304/**---------------------------------------------------------
1305 A use statement is met in the project file
1306*/
1307void Project::use_action (const cmt_string& name, const cmt_string& release)
1308{
1309 //cerr << "Use action " << name << " " << release << endl;
1310
1311 // A project with its release is specified
1312 //
1313 // Is this project already visible?
1314 // If not: look for it
1315 // + get CMTPROJECTPATH
1316 // + search from all entries of CMTPROJECTPATH : p(i)/<name>/<release>
1317 // + when found, this should become a new CMTPATH entry
1318 // + the new project is then parsed ... etc...
1319
1320 cmt_string cmtprojectpath = CmtSystem::getenv ("CMTPROJECTPATH");
1321 cmt_string sep;
1322 sep = CmtSystem::path_separator ();
1323
1324 //cerr << "cmtprojectpath = " << cmtprojectpath << endl;
1325 CmtSystem::cmt_string_vector items;
1326 CmtSystem::split (cmtprojectpath, sep, items);
1327
1328 bool found = false;
1329
1330 for (int i = 0; i < items.size (); i++)
1331 {
1332 const cmt_string& item = items[i];
1333 cmt_string p = item;
1334 p += CmtSystem::file_separator ();
1335 p += name;
1336 p += CmtSystem::file_separator ();
1337 p += release;
1338
1339 if (CmtSystem::test_directory (p))
1340 {
1341 //cerr << "Project directory " << p << " exists " << endl;
1342
1343 found = true;
1344
1345 IProjectFactory& factory = ProjectFactory::instance ();
1346
1347 factory.create_project (name, p, "ProjectPath", this);
1348
1349 break;
1350 }
1351 }
1352
1353 if (!found)
1354 {
1355 Project* p = Project::find_by_name (name);
1356
1357 if (p != 0)
1358 {
1359 found = true;
1360
1361 p->add_parent (this);
1362 add_child (p);
1363
1364 update_strategies_from_children ();
1365 }
1366 }
1367
1368 if (!found && (cmtprojectpath != ""))
1369 {
1370 cerr << "#CMT> Project " << name << " " << release << " requested by " << m_name << " not found in CMTPROJECTPATH" << endl;
1371 }
1372}
1373
1374
1375//----------------------------------------------------------
1376Project& Project::operator = (const Project& other)
1377{
1378 m_name = other.m_name;
1379 m_cmtpath = other.m_cmtpath;
1380 m_cmtpath_pwd = other.m_cmtpath_pwd;
1381 m_cmtpath_source = other.m_cmtpath_source;
1382
1383 return (*this);
1384}
1385
1386//----------------------------------------------------------
1387bool Project::operator == (const cmt_string& name) const
1388{
1389 return ((m_name == name));
1390}
1391
1392//----------------------------------------------------------
1393bool Project::operator != (const cmt_string& name) const
1394{
1395 return ((m_name != name));
1396}
1397
1398//----------------------------------------------------------
1399void Project::show ()
1400{
1401 static int level = 0;
1402
1403 bool is_current = false;
1404
1405 cmt_string here = CmtSystem::pwd ();
1406
1407 if (here.find (m_cmtpath) == 0)
1408 {
1409 if (m_cmtpath_source != "default path")
1410 {
1411 is_current = true;
1412 }
1413 }
1414
1415 for (int tab = 0; tab < level; tab++) cout << " ";
1416 cout << m_name << " " << m_release << " (in " << m_cmtpath << ")";
1417
1418 if (is_current) cout << " (current)";
1419
1420 int i;
1421
1422 for (i = 0; i < m_parents.size (); i++)
1423 {
1424 Project* p = m_parents[i];
1425 if (p == 0) continue;
1426 cout << " P=" << p->get_name ();
1427 }
1428
1429 for (i = 0; i < m_children.size (); i++)
1430 {
1431 Project* p = m_children[i];
1432 if (p == 0) continue;
1433 cout << " C=" << p->get_name ();
1434 }
1435
1436 cout << endl;
1437
1438 if (m_visited) return;
1439
1440 m_visited = true;
1441
1442 for (i = 0; i < m_children.size (); i++)
1443 {
1444 Project* p = m_children[i];
1445 if (p == 0) continue;
1446 level++;
1447 p->show ();
1448 level--;
1449 }
1450}
1451
1452
1453//----------------------------------------------------------
1454void Project::show_specified_strategies () const
1455{
1456 int i;
1457
1458 for (i = 0; i < m_strategies.size (); i++)
1459 {
1460 const Strategy& s = m_strategies[i];
1461 if (s.m_specified)
1462 {
1463 const StrategyDef* def = s.m_definition;
1464
1465 cout << "# Project " << m_name
1466 << " sets " << def->m_keyword
1467 << " strategy to " << ((s.m_value) ? def->m_on_value : def->m_off_value);
1468
1469 if (s.m_context != "")
1470 {
1471 cout << " (from package " << s.m_context << ")";
1472 }
1473
1474 cout << endl;
1475 }
1476 }
1477}
1478
1479//----------------------------------------------------------
1480bool Project::has_strategy (const StrategyDef* definition) const
1481{
1482 int i;
1483
1484 for (i = 0; i < m_strategies.size (); i++)
1485 {
1486 const Strategy& s = m_strategies[i];
1487 if (s.m_definition == definition)
1488 {
1489 return (true);
1490 }
1491 }
1492
1493 return (false);
1494}
1495
1496//----------------------------------------------------------
1497bool Project::get_strategy (const cmt_string& name) const
1498{
1499 static StrategyMgr& mgr = StrategyMgr::instance ();
1500
1501 StrategyDef* def = mgr.find_strategy (name);
1502 if (def == 0)
1503 {
1504 cerr << "#CMT> strategy " << name << " undefined" << endl;
1505 return (false);
1506 }
1507
1508 return (get_strategy (def));
1509}
1510
1511//----------------------------------------------------------
1512bool Project::is_specified (const StrategyDef* definition) const
1513{
1514 int i;
1515
1516 for (i = 0; i < m_strategies.size (); i++)
1517 {
1518 Strategy& s = m_strategies[i];
1519 if (s.m_definition == definition)
1520 {
1521 // This strategy is applied in this project
1522 return (s.m_specified);
1523 }
1524 }
1525
1526 // This strategy is not applied in this project
1527 return (false);
1528}
1529
1530//----------------------------------------------------------
1531bool Project::get_strategy (const StrategyDef* def) const
1532{
1533 int i;
1534
1535 for (i = 0; i < m_strategies.size (); i++)
1536 {
1537 Strategy& s = m_strategies[i];
1538 if (s.m_definition == def)
1539 {
1540 // This strategy is applied in this project
1541 if (s.m_specified)
1542 {
1543 return (s.m_specified_value);
1544 }
1545 return (s.m_value);
1546 }
1547 }
1548
1549 // This strategy is not applied in this project
1550 return (def->m_default_value);
1551}
1552
1553//----------------------------------------------------------
1554void Project::set_default_strategy (const cmt_string& name)
1555{
1556 static StrategyMgr& mgr = StrategyMgr::instance ();
1557
1558 StrategyDef* def = mgr.find_strategy (name);
1559 if (def == 0)
1560 {
1561 cerr << "#CMT> strategy " << name << " undefined" << endl;
1562 return;
1563 }
1564
1565 update_strategy (def, def->m_default_value);
1566}
1567
1568
1569//----------------------------------------------------------
1570void Project::set_strategy (const cmt_string& name, const cmt_string& value, const cmt_string& context)
1571{
1572 static StrategyMgr& mgr = StrategyMgr::instance ();
1573
1574 StrategyDef* def = mgr.find_strategy (name);
1575 if (def == 0)
1576 {
1577 cerr << "#CMT> strategy " << name << " undefined" << endl;
1578 return;
1579 }
1580
1581 bool b_value = false;
1582
1583 if (value == def->m_on_value)
1584 {
1585 b_value = true;
1586 }
1587 else if (value == def->m_off_value)
1588 {
1589 b_value = false;
1590 }
1591 else
1592 {
1593 cerr << "#CMT> requested strategy value " << value << " undefined in strategy " << name << endl;
1594 return;
1595 }
1596
1597 set_strategy (def, b_value, context);
1598}
1599
1600//----------------------------------------------------------
1601void Project::set_strategy (StrategyDef* definition, bool b_value, const cmt_string& context)
1602{
1603 bool need_strategy = true;
1604
1605 int i;
1606
1607 for (i = 0; i < m_strategies.size (); i++)
1608 {
1609 Strategy& s = m_strategies[i];
1610 if (s.m_definition == definition)
1611 {
1612 // This strategy is already applied in this project. Let's change it's value
1613 s.set (definition, b_value, get_name ());
1614 if (context != "")
1615 {
1616 if (s.m_context != "") s.m_context += " ";
1617 s.m_context += context;
1618 }
1619 need_strategy = false;
1620 break;
1621 }
1622 }
1623
1624 if (need_strategy)
1625 {
1626 // This strategy is not yet applied in this project.
1627
1628 Strategy& s = m_strategies.add ();
1629 s.clear ();
1630 s.set (definition, b_value, get_name ());
1631 s.m_context = context;
1632 }
1633
1634 for (i = 0; i < m_parents.size (); i++)
1635 {
1636 Project* project = m_parents[i];
1637
1638 project->update_strategy (definition, b_value);
1639 }
1640}
1641
1642/**----------------------------------------------------------
1643 The strategy value is changed because of indirect influences
1644 - default strategy at initialization time
1645 - change in the children
1646 - change in the children list
1647
1648 (This is not a specification : see the set_strategy method)
1649 */
1650void Project::update_strategy (StrategyDef* definition, bool b_value)
1651{
1652 bool need_strategy = true;
1653 bool specified = false;
1654
1655 int i;
1656
1657 for (i = 0; i < m_strategies.size (); i++)
1658 {
1659 Strategy& s = m_strategies[i];
1660 if (s.m_definition == definition)
1661 {
1662 need_strategy = false;
1663
1664 if (!s.m_specified)
1665 {
1666 // This strategy is already applied in this project. Let's change it's value
1667 s.update (definition, b_value, get_name ());
1668 }
1669 else
1670 {
1671 specified = true;
1672 }
1673 break;
1674 }
1675 }
1676
1677 if (need_strategy)
1678 {
1679 // This strategy is not yet applied in this project.
1680
1681 Strategy& s = m_strategies.add ();
1682 s.clear ();
1683 s.update (definition, b_value, get_name ());
1684 }
1685
1686 if (!specified)
1687 {
1688 for (i = 0; i < m_parents.size (); i++)
1689 {
1690 Project* project = m_parents[i];
1691
1692 project->update_strategy (definition, b_value);
1693 }
1694 }
1695}
1696
1697/**----------------------------------------------------------
1698 At least one of the children has changed this strategy
1699 Or the list of children has changed.
1700 We need to update the strategy value accordingly
1701 This will not change the specified value for this strategy
1702 */
1703void Project::update_strategy_from_children (StrategyDef* definition)
1704{
1705 // If this strategy is specified we don't care what happens from the children
1706
1707 //cerr << "Updating strategy " << definition->m_name << " from children for project " << m_name << endl;
1708
1709 int i;
1710
1711 for (i = 0; i < m_strategies.size (); i++)
1712 {
1713 Strategy& s = m_strategies[i];
1714 if (s.m_definition == definition)
1715 {
1716 // This strategy is applied in this project.
1717
1718 if (s.m_specified)
1719 {
1720 // There will be no impact since the strategy is specified
1721
1722 //cerr << "This strategy is specified in this project" << endl;
1723 return;
1724 }
1725
1726 break;
1727 }
1728 }
1729
1730 // The strategy is not specified locally so we will now figure out
1731 // which strategy has to be considered from the mixture of specifications
1732 // from all children.
1733
1734 // Algorithm:
1735 // - We consider children by pairs
1736 // - a child that specifies its strategy wins over a child that does not
1737 // - when the two children have the same level of priority we consider the priority value
1738
1739 Project* selected = 0;
1740 bool selected_is_specified = false;
1741 bool selected_value = definition->m_default_value;
1742
1743 for (i = 0; i < m_children.size (); i++)
1744 {
1745 Project* p = m_children[i];
1746
1747 //cerr << "Checking strategy for child " << p->get_name () << endl;
1748
1749 bool is_specified = p->is_specified (definition);
1750 bool value = p->get_strategy (definition);
1751
1752 if (selected == 0)
1753 {
1754 selected = p;
1755 selected_is_specified = is_specified;
1756 selected_value = value;
1757 continue;
1758 }
1759
1760 if (is_specified == selected_is_specified)
1761 {
1762 if (selected_value != value)
1763 {
1764 // same level of priority but different values -> we must decide
1765 bool priority_value = definition->m_priority_value;
1766 if (value == priority_value)
1767 {
1768 selected = p;
1769 selected_is_specified = is_specified;
1770 selected_value = value;
1771 }
1772 }
1773 }
1774 else
1775 {
1776 if (is_specified)
1777 {
1778 selected = p;
1779 selected_is_specified = is_specified;
1780 selected_value = value;
1781 }
1782 }
1783 }
1784
1785 update_strategy (definition, selected_value);
1786}
1787
1788/**----------------------------------------------------------
1789 At least one of the children has changed its strategies
1790 Or the list of children has changed.
1791 We need to update the strategy values accordingly
1792 This will not change the specified values
1793 */
1794void Project::update_strategies_from_children ()
1795{
1796 StrategyDef::StrategyDefs& defs = StrategyMgr::get_definitions ();
1797
1798 //cerr << "Updating strategies from children for project " << m_name << endl;
1799
1800 int i;
1801
1802 for (i = 0; i < defs.size (); i++)
1803 {
1804 StrategyDef* def = defs[i];
1805
1806 update_strategy_from_children (def);
1807 }
1808
1809 for (i = 0; i < m_parents.size (); i++)
1810 {
1811 Project* p = m_parents[i];
1812 p->update_strategies_from_children ();
1813 }
1814}
1815
1816/**----------------------------------------------------------
1817 The StrategyMgr singleton
1818 */
1819StrategyMgr& StrategyMgr::instance ()
1820{
1821 static StrategyMgr me;
1822 return (me);
1823}
1824
1825/**----------------------------------------------------------
1826 The StrategyMgr constructor
1827 Here are primarily constructed all strategy definitions
1828 */
1829StrategyMgr::StrategyMgr ()
1830{
1831 m_defs.clear ();
1832
1833 StrategyDef* s;
1834
1835 s = new StrategyDef;
1836 s->m_keyword = "build";
1837 s->m_name = "BuildPrototypes";
1838 s->m_on_value = "prototypes";
1839 s->m_off_value = "no_prototypes";
1840 s->m_default_value = true;
1841 s->m_priority_value = false;
1842
1843 m_defs.push_back (s);
1844
1845 s = new StrategyDef;
1846 s->m_keyword = "build";
1847 s->m_name = "InstallArea";
1848 s->m_on_value = "with_installarea";
1849 s->m_off_value = "without_installarea";
1850 s->m_default_value = false;
1851 s->m_priority_value = true;
1852
1853 m_defs.push_back (s);
1854
1855 s = new StrategyDef;
1856 s->m_keyword = "setup";
1857 s->m_name = "SetupConfig";
1858 s->m_on_value = "config";
1859 s->m_off_value = "no_config";
1860 s->m_default_value = true;
1861 s->m_priority_value = false;
1862
1863 m_defs.push_back (s);
1864
1865 s = new StrategyDef;
1866 s->m_keyword = "setup";
1867 s->m_name = "SetupRoot";
1868 s->m_on_value = "root";
1869 s->m_off_value = "no_root";
1870 s->m_default_value = true;
1871 s->m_priority_value = false;
1872
1873 m_defs.push_back (s);
1874
1875 s = new StrategyDef;
1876 s->m_keyword = "setup";
1877 s->m_name = "SetupCleanup";
1878 s->m_on_value = "cleanup";
1879 s->m_off_value = "no_cleanup";
1880 s->m_default_value = true;
1881 s->m_priority_value = false;
1882
1883 m_defs.push_back (s);
1884}
1885
1886/**----------------------------------------------------------
1887 Find a strategy definition by its name
1888 */
1889StrategyDef* StrategyMgr::find_strategy (const cmt_string& name)
1890{
1891 static StrategyMgr& me = instance ();
1892
1893 int i;
1894
1895 for (i = 0; i < me.m_defs.size (); i++)
1896 {
1897 StrategyDef* def = me.m_defs[i];
1898 if (def->m_name == name)
1899 {
1900 return (def);
1901 }
1902 }
1903
1904 return (0);
1905}
1906
1907/**----------------------------------------------------------
1908 Retreive the default value defined for a given strategy
1909 */
1910bool StrategyMgr::get_default_strategy (const cmt_string& name)
1911{
1912 StrategyDef* def = find_strategy (name);
1913 if (def == 0) return (false);
1914 return (def->m_default_value);
1915}
1916
1917/**----------------------------------------------------------
1918 Retreive the priority value defined for a given strategy
1919 This value is used when two children of a project request two conflicting strategy values
1920 */
1921bool StrategyMgr::get_priority_strategy (const cmt_string& name)
1922{
1923 StrategyDef* def = find_strategy (name);
1924 if (def == 0) return (false);
1925 return (def->m_priority_value);
1926}
1927
1928/**----------------------------------------------------------
1929 Return the vector of all existing strategy definitions
1930 */
1931StrategyDef::StrategyDefs& StrategyMgr::get_definitions ()
1932{
1933 static StrategyMgr& me = instance ();
1934
1935 return (me.m_defs);
1936}
1937
1938//-----------------------------------------------------------
1939Strategy::Strategy ()
1940{
1941 clear ();
1942}
1943
1944//-----------------------------------------------------------
1945void Strategy::clear ()
1946{
1947 m_definition = 0;
1948 m_specified = false;
1949 m_specified_value = false;
1950 m_value = false;
1951 m_on_tag = 0;
1952 m_off_tag = 0;
1953}
1954
1955/**----------------------------------------------------------
1956 Specify a new value for this strategy.
1957 This only happens when a strategy statement is met in a project file or in a requirements file.
1958 */
1959void Strategy::set (StrategyDef* definition, bool value, const cmt_string& project_name)
1960{
1961 //cerr << "Setting strategy " << definition->m_name << " for project " << project_name << " to " << value << endl;
1962
1963 m_definition = definition;
1964 m_specified = true;
1965 m_specified_value = value;
1966
1967 update (definition, value, project_name);
1968}
1969
1970/**----------------------------------------------------------
1971 Change the effective value for this strategy.
1972 This has no impact on to the specified value.
1973 This will adapt the tag settings
1974 */
1975void Strategy::update (StrategyDef* definition, bool value, const cmt_string& project_name)
1976{
1977 //cerr << "Updating strategy " << definition->m_name << " for project " << project_name << " to " << value << endl;
1978
1979 m_value = value;
1980 m_definition = definition;
1981
1982 cmt_string to_tag_name = project_name;
1983 cmt_string to_untag_name = project_name;
1984
1985 to_tag_name += "_";
1986 to_untag_name += "_";
1987
1988 if (m_value)
1989 {
1990 to_tag_name += m_definition->m_on_value;
1991 to_untag_name += m_definition->m_off_value;
1992 }
1993 else
1994 {
1995 to_tag_name += m_definition->m_off_value;
1996 to_untag_name += m_definition->m_on_value;
1997 }
1998
1999 m_on_tag = Tag::find (to_tag_name);
2000 m_off_tag = Tag::find (to_untag_name);
2001
2002 if (m_on_tag == 0)
2003 {
2004 m_on_tag = Tag::add (to_tag_name, PriorityConfig, "PROJECT", 0);
2005 m_off_tag = Tag::add (to_untag_name, PriorityConfig, "PROJECT", 0);
2006
2007 m_on_tag->add_tag_exclude (m_off_tag);
2008 m_off_tag->add_tag_exclude (m_on_tag);
2009 }
2010
2011 m_off_tag->unmark ();
2012 m_on_tag->mark ();
2013}
2014
2015const cmt_string& StrategyDef::get_default_value () const
2016{
2017 if (m_default_value)
2018 {
2019 return (m_on_value);
2020 }
2021 else
2022 {
2023 return (m_off_value);
2024 }
2025}
2026
Note: See TracBrowser for help on using the repository browser.