source: CMT/v1r18p20051101/source/cmt_project.cxx @ 597

Last change on this file since 597 was 100, checked in by arnault, 19 years ago

Fix a bug for releaseless projects on Windows CL#286

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