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

Last change on this file since 272 was 272, checked in by garonne, 18 years ago

See CL 313

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