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

Last change on this file since 97 was 97, checked in by arnault, 20 years ago

Protection against single level directories in CMTPATH (/xxx) see CL#285

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