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

Last change on this file since 400 was 400, checked in by arnault, 18 years ago

Text formatting
Sending warnings & errors to stderr
Using internally PWD for every cd/pwd
CL 327

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