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

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

Implement ticket #14 - See CL 292

  • 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 = Symbol::get_env_value ("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 = Symbol::get_env_value ("CMTPROJECTPATH");
1430
1431 cmt_string sep;
1432 sep = CmtSystem::path_separator ();
1433
1434 //cerr << "cmtprojectpath = " << cmtprojectpath << endl;
1435 CmtSystem::cmt_string_vector items;
1436 CmtSystem::split (cmtprojectpath, sep, items);
1437
1438 bool found = false;
1439
1440 for (int i = 0; i < items.size (); i++)
1441 {
1442 const cmt_string& item = items[i];
1443 cmt_string p = item;
1444 p += CmtSystem::file_separator ();
1445 p += name;
1446 if (release != "")
1447 {
1448 p += CmtSystem::file_separator ();
1449 p += release;
1450 }
1451
1452 if (CmtSystem::test_directory (p))
1453 {
1454 //cerr << "Project directory " << p << " exists " << endl;
1455
1456 found = true;
1457
1458 IProjectFactory& factory = ProjectFactory::instance ();
1459
1460 factory.create_project (name, p, "ProjectPath", this);
1461
1462 break;
1463 }
1464 }
1465
1466 if (!found)
1467 {
1468 Project* p = Project::find_by_name (name);
1469
1470 if (p != 0)
1471 {
1472 found = true;
1473
1474 p->add_parent (this);
1475 add_child (p);
1476
1477 update_strategies_from_children ();
1478 }
1479 }
1480
1481 if (!found && (cmtprojectpath != ""))
1482 {
1483 cerr << "#CMT> Project " << name << " " << release << " requested by " << m_name << " not found in CMTPROJECTPATH" << endl;
1484 }
1485}
1486
1487
1488//----------------------------------------------------------
1489Project& Project::operator = (const Project& other)
1490{
1491 m_name = other.m_name;
1492 m_cmtpath = other.m_cmtpath;
1493 m_cmtpath_pwd = other.m_cmtpath_pwd;
1494 m_cmtpath_source = other.m_cmtpath_source;
1495
1496 return (*this);
1497}
1498
1499//----------------------------------------------------------
1500bool Project::operator == (const cmt_string& name) const
1501{
1502 return ((m_name == name));
1503}
1504
1505//----------------------------------------------------------
1506bool Project::operator != (const cmt_string& name) const
1507{
1508 return ((m_name != name));
1509}
1510
1511//----------------------------------------------------------
1512void Project::show ()
1513{
1514 static int level = 0;
1515
1516 bool is_current = false;
1517
1518 cmt_string here = CmtSystem::pwd ();
1519
1520 if (here.find (m_cmtpath) == 0)
1521 {
1522 if (m_cmtpath_source != "default path")
1523 {
1524 is_current = true;
1525 }
1526 }
1527
1528 for (int tab = 0; tab < level; tab++) cout << " ";
1529 cout << m_name << " " << m_release << " (in " << m_cmtpath << ")";
1530
1531 if (is_current) cout << " (current)";
1532
1533 int i;
1534
1535 for (i = 0; i < m_parents.size (); i++)
1536 {
1537 Project* p = m_parents[i];
1538 if (p == 0) continue;
1539 cout << " P=" << p->get_name ();
1540 }
1541
1542 for (i = 0; i < m_children.size (); i++)
1543 {
1544 Project* p = m_children[i];
1545 if (p == 0) continue;
1546 cout << " C=" << p->get_name ();
1547 }
1548
1549 cout << endl;
1550
1551 if (m_visited) return;
1552
1553 m_visited = true;
1554
1555 for (i = 0; i < m_children.size (); i++)
1556 {
1557 Project* p = m_children[i];
1558 if (p == 0) continue;
1559 level++;
1560 p->show ();
1561 level--;
1562 }
1563}
1564
1565
1566//----------------------------------------------------------
1567void Project::show_specified_strategies () const
1568{
1569 int i;
1570
1571 for (i = 0; i < m_strategies.size (); i++)
1572 {
1573 const Strategy& s = m_strategies[i];
1574 if (s.m_specified)
1575 {
1576 const StrategyDef* def = s.m_definition;
1577
1578 cout << "# Project " << m_name
1579 << " sets " << def->m_keyword
1580 << " strategy to " << ((s.m_value) ? def->m_on_value : def->m_off_value);
1581
1582 if (s.m_context != "")
1583 {
1584 cout << " (from package " << s.m_context << ")";
1585 }
1586
1587 cout << endl;
1588 }
1589 }
1590}
1591
1592//----------------------------------------------------------
1593bool Project::has_strategy (const StrategyDef* definition) const
1594{
1595 int i;
1596
1597 for (i = 0; i < m_strategies.size (); i++)
1598 {
1599 const Strategy& s = m_strategies[i];
1600 if (s.m_definition == definition)
1601 {
1602 return (true);
1603 }
1604 }
1605
1606 return (false);
1607}
1608
1609//----------------------------------------------------------
1610bool Project::get_strategy (const cmt_string& name) const
1611{
1612 static StrategyMgr& mgr = StrategyMgr::instance ();
1613
1614 StrategyDef* def = mgr.find_strategy (name);
1615 if (def == 0)
1616 {
1617 cerr << "#CMT> strategy " << name << " undefined" << endl;
1618 return (false);
1619 }
1620
1621 return (get_strategy (def));
1622}
1623
1624//----------------------------------------------------------
1625bool Project::is_specified (const StrategyDef* definition) const
1626{
1627 int i;
1628
1629 for (i = 0; i < m_strategies.size (); i++)
1630 {
1631 Strategy& s = m_strategies[i];
1632 if (s.m_definition == definition)
1633 {
1634 // This strategy is applied in this project
1635 return (s.m_specified);
1636 }
1637 }
1638
1639 // This strategy is not applied in this project
1640 return (false);
1641}
1642
1643//----------------------------------------------------------
1644bool Project::get_strategy (const StrategyDef* def) const
1645{
1646 int i;
1647
1648 for (i = 0; i < m_strategies.size (); i++)
1649 {
1650 Strategy& s = m_strategies[i];
1651 if (s.m_definition == def)
1652 {
1653 // This strategy is applied in this project
1654 if (s.m_specified)
1655 {
1656 return (s.m_specified_value);
1657 }
1658 return (s.m_value);
1659 }
1660 }
1661
1662 // This strategy is not applied in this project
1663 return (def->m_default_value);
1664}
1665
1666//----------------------------------------------------------
1667void Project::set_default_strategy (const cmt_string& name)
1668{
1669 static StrategyMgr& mgr = StrategyMgr::instance ();
1670
1671 StrategyDef* def = mgr.find_strategy (name);
1672 if (def == 0)
1673 {
1674 cerr << "#CMT> strategy " << name << " undefined" << endl;
1675 return;
1676 }
1677
1678 update_strategy (def, def->m_default_value);
1679}
1680
1681
1682//----------------------------------------------------------
1683void Project::set_strategy (const cmt_string& name, const cmt_string& value, const cmt_string& context)
1684{
1685 static StrategyMgr& mgr = StrategyMgr::instance ();
1686
1687 StrategyDef* def = mgr.find_strategy (name);
1688 if (def == 0)
1689 {
1690 cerr << "#CMT> strategy " << name << " undefined" << endl;
1691 return;
1692 }
1693
1694 bool b_value = false;
1695
1696 if (value == def->m_on_value)
1697 {
1698 b_value = true;
1699 }
1700 else if (value == def->m_off_value)
1701 {
1702 b_value = false;
1703 }
1704 else
1705 {
1706 cerr << "#CMT> requested strategy value " << value << " undefined in strategy " << name << endl;
1707 return;
1708 }
1709
1710 set_strategy (def, b_value, context);
1711}
1712
1713//----------------------------------------------------------
1714void Project::set_strategy (StrategyDef* definition, bool b_value, const cmt_string& context)
1715{
1716 bool need_strategy = true;
1717
1718 int i;
1719
1720 for (i = 0; i < m_strategies.size (); i++)
1721 {
1722 Strategy& s = m_strategies[i];
1723 if (s.m_definition == definition)
1724 {
1725 // This strategy is already applied in this project. Let's change it's value
1726 s.set (definition, b_value, get_name ());
1727 if (context != "")
1728 {
1729 if (s.m_context != "") s.m_context += " ";
1730 s.m_context += context;
1731 }
1732 need_strategy = false;
1733 break;
1734 }
1735 }
1736
1737 if (need_strategy)
1738 {
1739 // This strategy is not yet applied in this project.
1740
1741 Strategy& s = m_strategies.add ();
1742 s.clear ();
1743 s.set (definition, b_value, get_name ());
1744 s.m_context = context;
1745 }
1746
1747 for (i = 0; i < m_parents.size (); i++)
1748 {
1749 Project* project = m_parents[i];
1750
1751 project->update_strategy (definition, b_value);
1752 }
1753}
1754
1755/**----------------------------------------------------------
1756 The strategy value is changed because of indirect influences
1757 - default strategy at initialization time
1758 - change in the children
1759 - change in the children list
1760
1761 (This is not a specification : see the set_strategy method)
1762 */
1763void Project::update_strategy (StrategyDef* definition, bool b_value)
1764{
1765 bool need_strategy = true;
1766 bool specified = false;
1767
1768 int i;
1769
1770 for (i = 0; i < m_strategies.size (); i++)
1771 {
1772 Strategy& s = m_strategies[i];
1773 if (s.m_definition == definition)
1774 {
1775 need_strategy = false;
1776
1777 if (!s.m_specified)
1778 {
1779 // This strategy is already applied in this project. Let's change it's value
1780 s.update (definition, b_value, get_name ());
1781 }
1782 else
1783 {
1784 specified = true;
1785 }
1786 break;
1787 }
1788 }
1789
1790 if (need_strategy)
1791 {
1792 // This strategy is not yet applied in this project.
1793
1794 Strategy& s = m_strategies.add ();
1795 s.clear ();
1796 s.update (definition, b_value, get_name ());
1797 }
1798
1799 if (!specified)
1800 {
1801 for (i = 0; i < m_parents.size (); i++)
1802 {
1803 Project* project = m_parents[i];
1804
1805 project->update_strategy (definition, b_value);
1806 }
1807 }
1808}
1809
1810/**----------------------------------------------------------
1811 At least one of the children has changed this strategy
1812 Or the list of children has changed.
1813 We need to update the strategy value accordingly
1814 This will not change the specified value for this strategy
1815 */
1816void Project::update_strategy_from_children (StrategyDef* definition)
1817{
1818 // If this strategy is specified we don't care what happens from the children
1819
1820 //cerr << "Updating strategy " << definition->m_name << " from children for project " << m_name << endl;
1821
1822 int i;
1823
1824 for (i = 0; i < m_strategies.size (); i++)
1825 {
1826 Strategy& s = m_strategies[i];
1827 if (s.m_definition == definition)
1828 {
1829 // This strategy is applied in this project.
1830
1831 if (s.m_specified)
1832 {
1833 // There will be no impact since the strategy is specified
1834
1835 //cerr << "This strategy is specified in this project" << endl;
1836 return;
1837 }
1838
1839 break;
1840 }
1841 }
1842
1843 // The strategy is not specified locally so we will now figure out
1844 // which strategy has to be considered from the mixture of specifications
1845 // from all children.
1846
1847 // Algorithm:
1848 // - We consider children by pairs
1849 // - a child that specifies its strategy wins over a child that does not
1850 // - when the two children have the same level of priority we consider the priority value
1851
1852 Project* selected = 0;
1853 bool selected_is_specified = false;
1854 bool selected_value = definition->m_default_value;
1855
1856 for (i = 0; i < m_children.size (); i++)
1857 {
1858 Project* p = m_children[i];
1859
1860 //cerr << "Checking strategy for child " << p->get_name () << endl;
1861
1862 bool is_specified = p->is_specified (definition);
1863 bool value = p->get_strategy (definition);
1864
1865 if (selected == 0)
1866 {
1867 selected = p;
1868 selected_is_specified = is_specified;
1869 selected_value = value;
1870 continue;
1871 }
1872
1873 if (is_specified == selected_is_specified)
1874 {
1875 if (selected_value != value)
1876 {
1877 // same level of priority but different values -> we must decide
1878 bool priority_value = definition->m_priority_value;
1879 if (value == priority_value)
1880 {
1881 selected = p;
1882 selected_is_specified = is_specified;
1883 selected_value = value;
1884 }
1885 }
1886 }
1887 else
1888 {
1889 if (is_specified)
1890 {
1891 selected = p;
1892 selected_is_specified = is_specified;
1893 selected_value = value;
1894 }
1895 }
1896 }
1897
1898 update_strategy (definition, selected_value);
1899}
1900
1901/**----------------------------------------------------------
1902 At least one of the children has changed its strategies
1903 Or the list of children has changed.
1904 We need to update the strategy values accordingly
1905 This will not change the specified values
1906 */
1907void Project::update_strategies_from_children ()
1908{
1909 StrategyDef::StrategyDefs& defs = StrategyMgr::get_definitions ();
1910
1911 //cerr << "Updating strategies from children for project " << m_name << endl;
1912
1913 int i;
1914
1915 for (i = 0; i < defs.size (); i++)
1916 {
1917 StrategyDef* def = defs[i];
1918
1919 update_strategy_from_children (def);
1920 }
1921
1922 for (i = 0; i < m_parents.size (); i++)
1923 {
1924 Project* p = m_parents[i];
1925 p->update_strategies_from_children ();
1926 }
1927}
1928
1929/**----------------------------------------------------------
1930 The StrategyMgr singleton
1931 */
1932StrategyMgr& StrategyMgr::instance ()
1933{
1934 static StrategyMgr me;
1935 return (me);
1936}
1937
1938/**----------------------------------------------------------
1939 The StrategyMgr constructor
1940 Here are primarily constructed all strategy definitions
1941 */
1942StrategyMgr::StrategyMgr ()
1943{
1944 m_defs.clear ();
1945
1946 StrategyDef* s;
1947
1948 s = new StrategyDef;
1949 s->m_keyword = "build";
1950 s->m_name = "BuildPrototypes";
1951 s->m_on_value = "prototypes";
1952 s->m_off_value = "no_prototypes";
1953 s->m_default_value = true;
1954 s->m_priority_value = false;
1955
1956 m_defs.push_back (s);
1957
1958 s = new StrategyDef;
1959 s->m_keyword = "build";
1960 s->m_name = "InstallArea";
1961 s->m_on_value = "with_installarea";
1962 s->m_off_value = "without_installarea";
1963 s->m_default_value = false;
1964 s->m_priority_value = true;
1965
1966 m_defs.push_back (s);
1967
1968 s = new StrategyDef;
1969 s->m_keyword = "setup";
1970 s->m_name = "SetupConfig";
1971 s->m_on_value = "config";
1972 s->m_off_value = "no_config";
1973 s->m_default_value = true;
1974 s->m_priority_value = false;
1975
1976 m_defs.push_back (s);
1977
1978 s = new StrategyDef;
1979 s->m_keyword = "setup";
1980 s->m_name = "SetupRoot";
1981 s->m_on_value = "root";
1982 s->m_off_value = "no_root";
1983 s->m_default_value = true;
1984 s->m_priority_value = false;
1985
1986 m_defs.push_back (s);
1987
1988 s = new StrategyDef;
1989 s->m_keyword = "setup";
1990 s->m_name = "SetupCleanup";
1991 s->m_on_value = "cleanup";
1992 s->m_off_value = "no_cleanup";
1993 s->m_default_value = true;
1994 s->m_priority_value = false;
1995
1996 m_defs.push_back (s);
1997
1998 s = new StrategyDef;
1999 s->m_keyword = "structure";
2000 s->m_name = "VersionDirectory";
2001 s->m_on_value = "with_version_directory";
2002 s->m_off_value = "without_version_directory";
2003 if (Cmt::get_current_structuring_style () != without_version_directory)
2004 {
2005 s->m_default_value = true;
2006 s->m_priority_value = false;
2007 }
2008 else
2009 {
2010 s->m_default_value = false;
2011 s->m_priority_value = true;
2012 }
2013
2014 m_defs.push_back (s);
2015}
2016
2017/**----------------------------------------------------------
2018 Find a strategy definition by its name
2019 */
2020StrategyDef* StrategyMgr::find_strategy (const cmt_string& name)
2021{
2022 static StrategyMgr& me = instance ();
2023
2024 int i;
2025
2026 for (i = 0; i < me.m_defs.size (); i++)
2027 {
2028 StrategyDef* def = me.m_defs[i];
2029 if (def->m_name == name)
2030 {
2031 return (def);
2032 }
2033 }
2034
2035 return (0);
2036}
2037
2038/**----------------------------------------------------------
2039 Retreive the default value defined for a given strategy
2040 */
2041bool StrategyMgr::get_default_strategy (const cmt_string& name)
2042{
2043 StrategyDef* def = find_strategy (name);
2044 if (def == 0) return (false);
2045 return (def->m_default_value);
2046}
2047
2048/**----------------------------------------------------------
2049 Retreive the priority value defined for a given strategy
2050 This value is used when two children of a project request two conflicting strategy values
2051 */
2052bool StrategyMgr::get_priority_strategy (const cmt_string& name)
2053{
2054 StrategyDef* def = find_strategy (name);
2055 if (def == 0) return (false);
2056 return (def->m_priority_value);
2057}
2058
2059/**----------------------------------------------------------
2060 Return the vector of all existing strategy definitions
2061 */
2062StrategyDef::StrategyDefs& StrategyMgr::get_definitions ()
2063{
2064 static StrategyMgr& me = instance ();
2065
2066 return (me.m_defs);
2067}
2068
2069//-----------------------------------------------------------
2070Strategy::Strategy ()
2071{
2072 clear ();
2073}
2074
2075//-----------------------------------------------------------
2076void Strategy::clear ()
2077{
2078 m_definition = 0;
2079 m_specified = false;
2080 m_specified_value = false;
2081 m_value = false;
2082 m_on_tag = 0;
2083 m_off_tag = 0;
2084}
2085
2086/**----------------------------------------------------------
2087 Specify a new value for this strategy.
2088 This only happens when a strategy statement is met in a project file or in a requirements file.
2089 */
2090void Strategy::set (StrategyDef* definition, bool value, const cmt_string& project_name)
2091{
2092 //cerr << "Setting strategy " << definition->m_name << " for project " << project_name << " to " << value << endl;
2093
2094 m_definition = definition;
2095 m_specified = true;
2096 m_specified_value = value;
2097
2098 update (definition, value, project_name);
2099}
2100
2101/**----------------------------------------------------------
2102 Change the effective value for this strategy.
2103 This has no impact on to the specified value.
2104 This will adapt the tag settings
2105 */
2106void Strategy::update (StrategyDef* definition, bool value, const cmt_string& project_name)
2107{
2108 //cerr << "Updating strategy " << definition->m_name << " for project " << project_name << " to " << value << endl;
2109
2110 m_value = value;
2111 m_definition = definition;
2112
2113 cmt_string to_tag_name = project_name;
2114 cmt_string to_untag_name = project_name;
2115
2116 to_tag_name += "_";
2117 to_untag_name += "_";
2118
2119 if (m_value)
2120 {
2121 to_tag_name += m_definition->m_on_value;
2122 to_untag_name += m_definition->m_off_value;
2123 }
2124 else
2125 {
2126 to_tag_name += m_definition->m_off_value;
2127 to_untag_name += m_definition->m_on_value;
2128 }
2129
2130 m_on_tag = Tag::find (to_tag_name);
2131 m_off_tag = Tag::find (to_untag_name);
2132
2133 if (m_on_tag == 0)
2134 {
2135 m_on_tag = Tag::add (to_tag_name, PriorityConfig, "PROJECT", 0);
2136 m_off_tag = Tag::add (to_untag_name, PriorityConfig, "PROJECT", 0);
2137
2138 m_on_tag->add_tag_exclude (m_off_tag);
2139 m_off_tag->add_tag_exclude (m_on_tag);
2140 }
2141
2142 m_off_tag->unmark ();
2143 m_on_tag->mark ();
2144}
2145
2146const cmt_string& StrategyDef::get_default_value () const
2147{
2148 if (m_default_value)
2149 {
2150 return (m_on_value);
2151 }
2152 else
2153 {
2154 return (m_off_value);
2155 }
2156}
2157
Note: See TracBrowser for help on using the repository browser.