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

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

See C.L. 314

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