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

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

Fix a bug for releaseless projects on Windows CL#286

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