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

Last change on this file since 291 was 291, checked in by garonne, 19 years ago

commit de sauvegarde :)

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