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

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

Fix cmt_cvs WRT structure strategy - see CL#279

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