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

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

Fix bug in project hierarchy. See CL 265

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