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

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

fixed bug with the hidden type package

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