source: CMT/v1rbeta20p20061025/source/cmt_project.cxx@ 295

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

beta development 1

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