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

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

Fixing session - see CL#275

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