source: CMT/v1r25-branch/source/cmt_project.cxx @ 666

Last change on this file since 666 was 666, checked in by rybkin, 10 years ago

merge -r 664:665 HEAD

File size: 87.2 KB
Line 
1//-----------------------------------------------------------
2// Copyright Christian Arnault LAL-Orsay CNRS
3// arnault@lal.in2p3.fr
4// Modified by garonne@lal.in2p3.fr
5// Modified by Grigory Rybkin
6// See the complete license in cmt_license.txt "http://www.cecill.info".
7//-----------------------------------------------------------
8
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <ctype.h>
13
14#include "cmt_project.h"
15#include "cmt_database.h"
16#include "cmt_system.h"
17#include "cmt_awk.h"
18#include "cmt_syntax.h"
19#include "cmt_tag.h"
20#include "cmt_error.h"
21#include "cmt_log.h"
22
23class ProjectReader : public Awk
24{
25public:
26
27  ProjectReader ()
28  {
29  }
30 
31  const cmt_string& get_project_name () const
32  {
33    return (m_project);
34  }
35 
36  void filter (const cmt_string& line)
37  {
38    if (0 == line.size () ||
39        line[0] == '#') return;
40    CmtSystem::cmt_string_vector words;
41    CmtSystem::split (line, " \t", words);
42    if (words[0] == "project")
43      {
44        m_project = words[1];
45      }
46  }
47 
48private:
49  cmt_string m_project;
50};
51
52class ProjectPatcher : public Awk
53{
54public:
55
56  ProjectPatcher (const cmt_string& p) : m_project (p)
57  {
58  }
59
60  void commit ()
61  {
62    m_output.write (Project::get_project_file_name ());
63  }
64
65  void filter (const cmt_string& line)
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    m_output += "\n";
80  }
81 
82private:
83  cmt_string m_output;
84  const cmt_string& m_project;
85};
86
87IProjectFactory& ProjectFactory::instance ()
88{
89  static ProjectFactory me;
90 
91  return (me);
92}
93
94void ProjectFactory::reset ()
95{
96  Project::clear_all ();
97}
98
99static bool get_release_from_path (const CmtSystem::cmt_string_vector& items, 
100                                   const cmt_string& path, 
101                                   const cmt_string& name, 
102                                   cmt_string& real_name, 
103                                   cmt_string& release)
104{
105  bool result = false;
106
107  release = "";
108  real_name = "";
109
110  cmt_string p = path;
111
112  if ((items.size () == 0) && (name == ""))
113    {
114      // There is no CMTPROJECTPATH and no expected project name.
115      // We have no way to find a project structure
116      // So we only expect a 2-level structure.
117
118      CmtSystem::basename (p, release);
119      CmtSystem::dirname (p, p);
120      CmtSystem::basename (p, real_name);
121     
122      return (false);
123    }
124
125  for (;;)
126    {
127      if (p == "")
128        {
129          // Protection: we found no matching project name
130          // and path was outside any CMTPROJECTPATH
131
132          p = path;
133
134          CmtSystem::basename (p, release);
135          CmtSystem::dirname (p, p);
136          CmtSystem::basename (p, real_name);
137
138          return (false);
139        }
140
141      cmt_string n;
142
143      CmtSystem::basename (p, n);
144      CmtSystem::dirname (p, p);
145
146      if (n == name)
147        {
148          real_name = name;
149          result = true;
150          break;
151        }
152
153      CmtSystem::basename (p, real_name);
154
155      for (int i = 0; i < items.size (); i++)
156        {
157          const cmt_string& item = items[i];
158          if (p == item)
159            {
160              // We have reached an item of CMTPROJECTPATH, no need to continue
161              return (false);
162            }
163        }
164
165      if (release == "")
166        {
167          release = n;
168        }
169      else
170        {
171          cmt_string r;
172
173          r = n;
174          r += CmtSystem::file_separator ();
175          r += release;
176          release = r;
177        }
178    }
179
180  //cerr << "$CMT> GRFP> path=" << path << " name=" << name << " rel=" << release << endl;
181
182  return (result);
183}
184 
185
186/*
187  Every new CMTPATH entry becomes associated with a dedicated PROJECT
188  This function will understand this new entry to CMTPATH and understand it:
189  - it can correspond to an existing project (ie already declared)
190  - it's a new project
191  - then it tries to read and parse its project file
192*/
193Project* ProjectFactory::create_project (const cmt_string& specified_name,
194                                         const cmt_string& path,
195                                         const cmt_string& source,
196                                         Project* parent)
197{
198  cmt_string compressed_path = path;
199  CmtSystem::compress_path (compressed_path);
200  bool specify_name = (specified_name != "");
201
202  if (Cmt::get_debug ())
203    {
204      cout << "Creating project " << specified_name << " in " << path << " from " << source << " with parent " << ((parent==0)? "0" : parent->get_name ()) << endl;
205      Project::show_all ();
206    }
207
208  cmt_string sep;
209  sep = CmtSystem::path_separator ();
210
211  cmt_string cmtprojectpath = Symbol::get_env_value ("CMTPROJECTPATH"); 
212  CmtSystem::cmt_string_vector items;
213  CmtSystem::split (cmtprojectpath, sep, items);
214
215  cmt_string here = CmtSystem::pwd ();
216  if (!CmtSystem::cd (compressed_path)) return (0);
217  cmt_string pwd = CmtSystem::pwd ();
218
219  static Project::ProjectVector& Projects = Project::projects ();
220
221  int i;
222 
223  for (i = 0; i < Projects.size (); i++)
224    {
225      Project& p = Projects[i];
226     
227      if ((p.get_cmtpath () == compressed_path) ||
228          (p.get_cmtpath_pwd () == pwd) ||
229          (specify_name && (p.get_name () == specified_name)))
230        {
231          cmt_string r;
232          cmt_string n;
233
234          get_release_from_path (items, compressed_path, p.get_name (), n, r);
235
236          if (r != p.get_release ())
237            {
238              CmtMessage::warning ("Project " + p.get_name ()
239                                   + " requested with conflicting releases "
240                                   + p.get_release () + " and " + r
241                                   + ", latter (in " + compressed_path + ") ignored");
242              /*
243              CmtMessage::error ("Project " + p.get_name ()
244                                   + " requested with conflicting releases "
245                                   + p.get_release () + " and " + r);
246              */
247              /*
248              if (!Cmt::get_quiet ())
249                {
250                  cerr << "#CMT> Project " << p.get_name ()
251                       << " requested with conflicting releases " << p.get_release () << " and " << r << endl;
252                }
253              */
254              //CmtError::set (CmtError::project_release_conflict, p.get_name ());
255            }
256 
257          bool updated (false);
258          if (parent != 0)
259            {
260              if (!p.has_parent (parent) || !parent->has_child (&p))
261                {
262              p.add_parent (parent);
263              parent->add_child (&p);
264
265              // Since p is a new parent, we should propagate the settings UP.
266
267              parent->update_strategies_from_children ();
268              updated = true;
269                }
270
271            }
272
273          CmtSystem::cd (here);
274          if (updated) Project::order_all ();
275          return (&p);
276        }
277    }
278
279
280  Project* project = 0;
281  Project* cmt = 0;
282 
283  bool is_current = false;
284 
285  cmt_string name = specified_name;
286  cmt_string project_name;
287  cmt_string release;
288
289  //
290  // Figure out if this is the current project
291  //
292  //  if (here.find (pwd) == 0) is_current = true;
293
294  // In case there are symlinks
295
296  //  cmt_string here_real, pwd_real;
297  //cerr << "realpath_: create_project" << endl;
298  /*
299  if (CmtSystem::realpath_ (here, here_real) && CmtSystem::realpath_ (pwd, pwd_real))
300    {
301      if (here_real.find (pwd_real) == 0) is_current = true;
302    }
303  */
304  cmt_string pwd_real;
305  if (!CmtSystem::realpath_ (pwd, pwd_real))
306    {
307      CmtError::set (CmtError::file_access_error, "Cannot compute real path `" +
308                     pwd + "'");
309      CmtError::print ();
310      return 0;
311      //      if (Cmt::get_current_dir_real ().find (pwd_real) == 0) is_current = true;
312    }
313
314  cmt_string text;
315
316  /*
317    Now Figure out the project name from the project file
318    or does not specify the project name
319  */
320  bool has_project_file = false;
321
322  if (CmtSystem::cd ("cmt") && CmtSystem::test_file (Project::get_project_file_name ()))
323    {
324      has_project_file = true;
325      text.read (Project::get_project_file_name ());
326
327      ProjectReader reader;
328
329      reader.run (text);
330
331      project_name = reader.get_project_name ();
332    }
333
334  enum
335    {
336      without_project_file   = 0x01,
337      with_project_file      = 0x02,
338      without_project_name   = 0x04,
339      with_project_name      = 0x08,
340      without_specified_name = 0x10,
341      with_specified_name    = 0x20,
342      names_mismatch         = 0x40,
343      names_match            = 0x80
344    };
345
346  int status = ((has_project_file) ? with_project_file : without_project_file) |
347    ((has_project_file && (project_name != "")) ? with_project_name : without_project_name) |
348    ((specify_name) ? with_specified_name : without_specified_name) |
349    ((specify_name && has_project_file && (project_name == specified_name)) ? names_match : names_mismatch);
350
351  if (source == "default path")
352    {
353      name = "CMT";
354    }
355  else
356    {
357      cmt_string n;
358         
359      switch (status)
360        {
361        case with_project_file | without_project_name | without_specified_name | names_mismatch:
362
363          // The project is neither specified from the caller nor from the project file
364
365          /*
366            if (!Cmt::get_quiet ())
367            {
368            cerr << "#CMT> Warning: project name unspecified in project file." << endl;
369            }
370          */
371     
372          get_release_from_path (items, compressed_path, "", name, release);
373
374          break;
375         
376        case with_project_file | without_project_name | with_specified_name | names_mismatch:
377         
378          // The name is only specified from the caller
379          // find this specified name in the path
380         
381          if (get_release_from_path (items, compressed_path, specified_name, name, release))
382            {
383              // The specified name has been found from the path.
384              // We believe in the release spec.
385            }
386          else
387            {
388              // The specified name is not in the path.
389              /*
390                if (!Cmt::get_quiet ())
391                {
392                cerr << "#CMT> Warning: specified project name "
393                << specified_name
394                << " from the caller does not match path." << endl;
395                }
396              */
397              name = specified_name;
398            }
399         
400          break;
401         
402        case with_project_file | with_project_name | with_specified_name | names_match:
403         
404          // We have a double specification: from the caller and from the project file.
405          // And both specifications are consistent. 
406         
407          if (get_release_from_path (items, compressed_path, specified_name, name, release))
408            {
409              // The specified name has been found from the path.
410              // We believe in the release spec.
411            }
412          else
413            {
414              // The specified name is not in the path.
415              /*
416                if (!Cmt::get_quiet ())
417                {
418                cerr << "#CMT> Warning: specified project name "
419                << specified_name
420                << " from project file and from caller does not match path." << endl;
421                }
422              */
423              name = specified_name;
424            }
425         
426          break;
427         
428        case with_project_file | with_project_name | with_specified_name | names_mismatch:
429         
430          // We have a double specification: from the caller and from the project file.
431          // Specifications are inconsistent!!
432         
433          /*
434            if (!Cmt::get_quiet ())
435            {
436            cerr << "#CMT> Warning: specified project name "
437            << specified_name
438            << " inconsistent with name "
439            << project_name
440            << " from project file." << endl;
441            }
442          */
443         
444          if (get_release_from_path (items, compressed_path, specified_name, n, release))
445            {
446              // name from caller wins.
447            }
448          else if (get_release_from_path (items, compressed_path, project_name, name, release))
449            {
450              // name from project file wins.
451            }
452          else
453            {
454              // The specified name is not in the path.
455             
456              CmtMessage::warning ("none of specified project names "
457                                   + specified_name + " from graph and "
458                                   + project_name + " from project file match path.");
459              /*
460              if (!Cmt::get_quiet ())
461                {
462                  cerr << "#CMT> Warning: none of specified project names "
463                       << specified_name
464                       << " from graph and "
465                       << project_name
466                       << " from project file match path." << endl;
467                }
468              */
469
470              name = specified_name;
471            }
472         
473          break;
474         
475        case with_project_file | with_project_name | without_specified_name | names_mismatch:
476         
477          // Project name is specified in the project file but not from the caller.
478         
479          if (get_release_from_path (items, compressed_path, project_name, name, release))
480            {
481              // The specified name has been found from the path.
482              // We believe in the release spec.
483
484            }
485          else
486            {
487              // The specified name is not in the path.
488
489              /*
490                if (!Cmt::get_quiet ())
491                {
492                cerr << "#CMT> Warning: specified project name "
493                << project_name
494                << " from project file does not match path." << endl;
495                }
496              */
497
498              name = project_name;
499            }
500         
501          break;
502         
503        case without_project_file | without_project_name | without_specified_name | names_mismatch:
504         
505          // The project is not specified from the caller and there is no project file
506          // This corresponds to the backward compatibility
507          // For the moment, assume /name/release/ structure where release is one level only
508         
509          /*
510            if (!Cmt::get_quiet ())
511            {
512            cerr << "#CMT> Warning: project name is not specified "
513            << " (no project file)." << endl;
514            }
515          */
516         
517          CmtSystem::basename (compressed_path, release);
518          CmtSystem::dirname (compressed_path, name);
519          CmtSystem::basename (name, name);
520
521          if (name == "")
522            {
523              name = release;
524              release = "";
525            }
526         
527          break;
528         
529        case without_project_file | without_project_name | with_specified_name | names_mismatch:
530         
531          // The name is only specified from the caller
532          // find this specified name in the path
533         
534          if (get_release_from_path (items, compressed_path, specified_name, name, release))
535            {
536              // The specified name has been found from the path.
537              // We believe in the release spec.
538            }
539          else
540            {
541              // The specified name is not in the path.
542              /*
543                if (!Cmt::get_quiet ())
544                {
545                cerr << "#CMT> Warning: specified project name "
546                << specified_name
547                << " from project graph does not match path." << endl;
548                }
549              */
550              name = specified_name;
551            }
552         
553          break;
554        }
555    }
556
557  if (name == "")
558    {
559      name = "Project";
560    }
561
562  project = Project::add (name, release);
563     
564  if (parent != 0)
565    {
566      project->add_parent (parent);
567      parent->add_child (project);
568
569      // Since project is a new child, we should propagate the settings UP.
570
571      parent->update_strategies_from_children ();
572    }
573  /*
574  else if ((name != "CMTUSERCONTEXT") && (name != "CMTHOME"))
575    //  else
576    {
577      // this project has no parent thus it should become the top project.
578      // Let's look for all projects without parent.
579      // they will become children of this project.
580
581      for (i = 0; i < Projects.size (); i++)
582        {
583          Project* p = &(Projects[i]);
584          const cmt_string& n = p->get_name ();
585          if (n == name) continue;
586          //      if (p->get_name () == name) continue;
587          if ((n == "CMTUSERCONTEXT") || (n == "CMTHOME")) continue;
588          if (!p->has_parents ())
589            {
590              project->add_child (p);
591              p->add_parent (project);
592            }
593        }
594
595      // Since project is a new parent, we should upgrade its settings
596
597      project->update_strategies_from_children ();
598    }
599  */
600  if (source == "default path")
601    {
602      cmt = project;
603      is_current = false;
604    }
605
606  project->set_cmtpath (compressed_path);
607  project->set_cmtpath_real (pwd_real);
608  project->set_cmtpath_pwd (pwd);
609  project->set_cmtpath_source (source);
610
611  //  project->set_is_current (is_current);
612  /*
613  if (is_current)
614    {
615      //      cerr << "current: " << project->get_name () << endl;
616      //
617      // The current project defines a tag with its name
618      //
619
620      Tag* tag;
621     
622      tag = Tag::add (project->get_name (), PriorityConfig, "PROJECT", 0);
623      tag->mark ();
624    }
625  */
626
627  //  Project::order_all ();
628
629  if (text != "")
630    {
631      // Last step is to parse the project file
632
633      if (Cmt::get_debug ())
634        {
635          cout << "About to parse project file [" << text << "]" << endl;
636        }
637
638      // First create the Project.m_use for the policy
639
640      Use* project_use = Use::create (project->get_cmtpath(), 
641                                      "package_policy_for_project_" + project->get_name(),                                       
642                                      project->get_release (), "", "");                                                         
643
644      project_use->done      = true;
645      project_use->discarded = false;
646      project_use->m_hidden  = true;
647      project_use->selected  = true;
648      project_use->change_path (project->get_cmtpath(), project);
649      //      project_use->m_located = true;
650      cmt_map <Use*, bool> visited;
651      project_use->set_auto_imports(Unspecified, Off, visited);
652      //project_use->set_auto_imports(Off);
653      project_use->initial_scope = ScopePublic;     
654      project->set_use(project_use);
655     
656     
657      // add at the uses level ?????
658      /*static Use::UsePtrVector& uses = Use::get_ordered_uses ();
659        bool found = false;
660        int  size  = uses.size ();
661        cerr << "\n size:"<<size<< ":" << endl;     
662        for (int n = 0; n < size; n++)
663        {
664        Use* tuse = uses[n];
665        cerr << "\tpackage file [" << tuse->get_package_name() << "]" <<project_use->get_package_name()<< endl;                   
666        if (tuse->get_package_name()==project_use->get_package_name())
667        found=true;
668
669        }
670   
671        if (not found)
672        {
673        uses.push_back (project_use);
674        project_use->m_index = uses.size () - 1;
675        }
676      */
677
678      SyntaxParser::parse_project_file_text (text, 
679                                             Project::get_project_file_name (),
680                                             project);
681    }
682
683
684
685  CmtSystem::cd (here);
686  Project::order_all ();
687
688  return (project);
689}
690
691/*----------------------------------------------------------*/
692/*                                                          */
693/*  Operations on Projects                                  */
694/*                                                          */
695/*----------------------------------------------------------*/
696
697//----------------------------------------------------------
698bool Project::create (const cmt_string& name, 
699                      const cmt_string& release, 
700                      const cmt_string& path)
701{
702  cmt_string pwd = CmtSystem::pwd ();
703
704  if (CmtMessage::active (Error))
705    {
706  cerr << "------------------------------------------" << endl;
707  cerr << "Configuring environment for project " << name << " " << release << " (from " << pwd << ") ";
708
709  if (path != "")
710    {
711      cerr << " in " << path;
712    }
713
714  cerr << endl;
715  cerr << "CMT version " << Cmt::get_cmt_version () << "." << endl;
716  cerr << "------------------------------------------" << endl;
717    }
718
719  if (path != "")
720    {
721      if (!CmtSystem::mkdir (path))
722        {
723          CmtMessage::error ("Cannot create the " + path + " directory");
724          //          cerr << "Cannot create the " << path << " directory" << endl;
725          return (false);
726        }
727
728      if (!CmtSystem::cd (path))
729        {
730          CmtMessage::error ("Cannot access the " + path + " directory");
731          //          cerr << "Cannot access the " << path << " directory" << endl;
732          return (false);
733        }
734    }
735
736  if (!CmtSystem::mkdir (name))
737    {
738      CmtMessage::error ("Cannot create the " + name + " directory");
739      //      cerr << "Cannot create the " << name << " directory" << endl;
740      return (false);
741    }
742
743  if (!CmtSystem::cd (name))
744    {
745      CmtMessage::error ("Cannot access the " + name + " directory");
746      //      cerr << "Cannot access the " << name << " directory" << endl;
747      return (false);
748    }
749
750  if (release != "")
751    {
752      if (!CmtSystem::mkdir (release))
753        {
754          CmtMessage::error ("Cannot create the " + release + " directory");
755          //      cerr << "Cannot create the " << release << " directory" << endl;
756          return (false);
757        }
758     
759      if (!CmtSystem::cd (release))
760        {
761          CmtMessage::error ("Cannot access the " + release + " directory");
762          //      cerr << "Cannot access the " << release << " directory" << endl;
763          return (false);
764        }
765    }
766
767  if (!CmtSystem::test_directory ("cmt"))
768    {
769      if (!CmtSystem::mkdir ("cmt"))
770        {
771          CmtMessage::error ("Cannot create the cmt directory");
772          //          cerr << "Cannot create the cmt directory" << endl;
773          return (false);
774        }
775      else
776        {
777          if (CmtMessage::active (Info))
778            cerr << "Installing the cmt directory" << endl;
779        }
780    }
781
782  CmtSystem::cd ("cmt");
783
784  if (!CmtSystem::test_file (get_project_file_name ()))
785    {
786      if (CmtMessage::active (Info))
787        cerr << "Creating a new project file" << endl;
788
789      ofstream f (get_project_file_name ());
790      if (f)
791        {
792          f << "project " << name << endl;
793          f << endl;
794          f.close ();
795        }
796      else
797        {
798          CmtMessage::error ("Cannot create the project file");
799          //          cerr << "Cannot create the project file" << endl;
800          return (false);
801        }
802    }
803  else
804    {
805      cmt_string text;
806      text.read (get_project_file_name ());
807
808      ProjectPatcher p (name);
809
810      p.run (text);
811      p.commit ();
812
813      if (CmtMessage::active (Info))
814        cerr << "project file already there" << endl;
815    }
816
817  return (true);
818}
819
820//----------------------------------------------------------
821Project* Project::find_by_name (const cmt_string& name)
822{
823  static ProjectVector& Projects = projects ();
824
825  for (int i = 0; i < Projects.size (); i++)
826    {
827      Project& p = Projects[i];
828      if (p.m_name == name) return (&p);
829     
830    }
831
832  return (0);
833}
834
835//----------------------------------------------------------
836Project* Project::find_by_cmtpath (const cmt_string& cmtpath)
837{
838  cmt_string compressed_path = cmtpath;
839  CmtSystem::compress_path (compressed_path);
840
841  static ProjectVector& Projects = projects ();
842
843  for (int i = 0; i < Projects.size (); i++)
844    {
845      Project& p = Projects[i];
846
847      if (p.m_cmtpath == compressed_path) return (&p);
848      if (p.m_cmtpath_real == compressed_path) return (&p);
849      if (p.m_cmtpath_pwd == compressed_path) return (&p);
850    }
851
852  return (0);
853}
854
855//----------------------------------------------------------
856Project* Project::get_current ()
857{
858  /*
859  cmt_string here = CmtSystem::pwd ();
860
861  // In case there are symlinks
862  cmt_string here_real;
863  CmtSystem::realpath_ (here, here_real);
864  */
865  static ProjectVector& Projects = projects ();
866
867  for (int i = (Projects.size () - 1); i >= 0; i--)
868    {
869      Project& p = Projects[i];
870
871//       if (here.find (p.m_cmtpath_pwd) == 0)
872//      {
873//        result = &p;
874//      }
875
876//      if (here.find (p.m_cmtpath) == 0)
877      if (p.is_current ()) 
878        //      if (here_real.find (p.m_cmtpath_real) == 0)
879        {
880          return &p;
881        }
882    }
883
884  return 0;
885}
886
887//----------------------------------------------------------
888Project* Project::add (const cmt_string& name,
889                       const cmt_string& release)
890{
891  static ProjectVector& Projects = projects ();
892
893  {
894    Project* project;
895
896    project = find_by_name (name);
897    if (project != 0) 
898      {
899        //      if (!Cmt::get_quiet ())
900        //        {
901            if (release != project->get_release ())
902              {
903                //if (CmtMessage::active (Verbose))
904                CmtMessage::error ("Project " + name
905                                   + " requested with conflicting releases "
906                                   + project->get_release () + " and " + release);
907                //              cerr << "#CMT> Project " << name << " requested with conflicting releases " << project->get_release () << " and " << release << endl;
908                CmtError::set (CmtError::project_release_conflict, name);
909              }
910            //    }
911
912        // Project objects are recreated here to follow the hierarchy
913        // This duplication is needed for properly applying the strategies
914        Project& p = Projects.add ();
915
916        p.set_name (name);
917        p.set_release (release);
918        p.configure ();
919
920        return (&p);
921
922        //return (project);
923      }
924  }
925
926  Project& project = Projects.add ();
927  project.clear ();
928  project.set_name (name);
929  project.set_release (release);
930  project.configure ();
931
932  return (&project);
933}
934
935//----------------------------------------------------------
936Project::ProjectVector& Project::projects ()
937{
938  static Database& db = Database::instance ();
939  static ProjectVector& Projects = db.projects ();
940
941  return (Projects);
942}
943
944//----------------------------------------------------------
945Project::ProjectPtrVector& Project::ordered_projects ()
946{
947  static Database& db = Database::instance ();
948  static ProjectPtrVector& Projects = db.ordered_projects ();
949
950  return (Projects);
951}
952
953//----------------------------------------------------------
954void Project::order_all ()
955//Project::ProjectPtrVector Project::ordered_projects ()
956{
957  ProjectPtrVector OrderedProjects;
958  //  static ProjectPtrVector OrderedProjects;
959  static Project::ProjectPtrVector& orderedProjects = Project::ordered_projects ();
960
961  static Project::ProjectVector& Projects = Project::projects ();
962  const int size = Projects.size ();
963 
964  int offset (0);
965  int iuser (-1);
966  int ihome (-1);
967  for (int i = 0; i < 2; i++)
968    {
969      if (offset < size)
970        {
971          const cmt_string& name = Projects[offset].get_name ();
972          if (name == "CMTUSERCONTEXT")
973            {
974              iuser = offset;
975              ++offset;
976            }
977          else if (name == "CMTHOME")
978            {
979              ihome = offset;
980              ++offset;
981            }
982          else
983            break;
984        }
985    }
986
987  OrderedProjects.resize (size);
988
989  Use& use = Use::current();
990  cmt_string current_path;
991  cmt_string current_path_real;
992  if (use.located ())
993    {
994      current_path_real = use.get_realpath ();
995      if (current_path_real.size ())
996        CmtMessage::verbose ("Using current use realpath `" + current_path_real + "'");
997      else
998        {
999          current_path = use.real_path;
1000          CmtMessage::verbose ("Using current use real_path `" + current_path + "'");
1001        }
1002    }
1003  else
1004    current_path = Cmt::get_current_dir ();
1005
1006  if (0 == current_path_real.size () &&
1007      !CmtSystem::realpath_ (current_path, current_path_real))
1008    {
1009      CmtError::set (CmtError::file_access_error, "Cannot compute real path `" +
1010                     current_path + "'");
1011      CmtError::print ();
1012      return;
1013      //CmtMessage::error ("Cannot compute real path `" + Use::current().real_path + "'");
1014    }
1015
1016  Project* p_cur (0);
1017  for (int i = 0; i < size; i++)
1018    {
1019      Project& p = Projects[i];
1020      if (i >= offset)
1021        p.m_order = -1;
1022      else
1023        p.m_order = -2;
1024      p.m_visits = 0;
1025      //
1026      // The current project specification
1027      //
1028      if (current_path_real.find (p.get_cmtpath_real ()) == 0)
1029        {
1030          p_cur = &p;
1031          if (p.is_current ()) continue;
1032
1033          p.set_is_current (true);
1034          //
1035          // The current project defines a tag with its name
1036          //
1037         
1038          Tag* tag;
1039         
1040          tag = Tag::add (p.get_name (), PriorityConfig, "PROJECT", 0);
1041          tag->mark ("PROJECT");
1042        }
1043      else if (p.is_current ())
1044        {
1045          //
1046          // Unset the tag with its name
1047          //
1048          Tag* tag = Tag::find (p.get_name ());
1049          if (tag != 0)
1050            tag->unmark ();
1051
1052          p.set_is_current (false);
1053        }
1054    }
1055
1056  if (size == offset)
1057    {
1058      for (int i = 0; i < offset; i++)
1059        {
1060          Project* p = &(Projects[i]);
1061          OrderedProjects[i] = p;
1062        }
1063      /*
1064      if (2 == offset)
1065        {
1066          OrderedProjects[0]->add_child (OrderedProjects[1]);
1067          OrderedProjects[1]->add_parent (OrderedProjects[0]);
1068          OrderedProjects[0]->update_strategies_from_children ();
1069        }
1070      */
1071      for (int i = OrderedProjects.size () - 2; i >= 0; i--)
1072        {
1073          if (!OrderedProjects[i]->has_parents () &&
1074              OrderedProjects[i]->get_children_size () == 0)
1075            {
1076              OrderedProjects[i]->add_child (OrderedProjects[i + 1]);
1077              OrderedProjects[i]->update_strategies_from_children ();
1078              OrderedProjects[i]->erase_child (OrderedProjects[i + 1]);
1079            }
1080        }
1081
1082      orderedProjects = OrderedProjects;
1083      //      return OrderedProjects;
1084      return;
1085    }
1086
1087  Project* p (p_cur);
1088  //  Project* p = get_current ();
1089
1090  //  cerr << "get_current: " << p << " offset: " << offset << endl;
1091  /*
1092  if (p == 0)
1093    {
1094      p = &(Projects[offset]);
1095      //      p = &(Projects[0]);
1096    }
1097  */
1098  //  cerr << "p: " << p << " offset: " << offset << " name: " << p->get_name () << endl;
1099
1100  int order (-1);
1101  /*
1102  if ((p->get_name () != "CMTUSERCONTEXT") && (p->get_name () != "CMTHOME"))
1103    {
1104      ProjectPtrVector projs;
1105      p->m_order = ++order;
1106      //      p->m_visits++;
1107      projs.push_back (p);
1108     
1109      visit (offset, order, projs);
1110      //  visit (order, projs);
1111    }
1112  //  cerr << "order: " << order << endl;
1113  //  int unordered = size - offset - (order + 1);
1114  */
1115  ProjectPtrVector projs;
1116
1117  if (p != 0 && (p->get_name () != "CMTUSERCONTEXT") && (p->get_name () != "CMTHOME"))
1118    {
1119      p->m_order = ++order;
1120      projs.push_back (p);
1121    }
1122
1123  if (p == 0 ||
1124      !p->has_parents ())
1125    // may come from CMTPATH entry
1126      /*
1127      (!p->has_parents () && p->get_children_size () == 0)
1128      // comes from CMTPATH entry
1129      )
1130      */
1131    {
1132      for (int i = offset; i < size; i++)
1133        {
1134          Project* q = &(Projects[i]);
1135          if (q != p && !q->has_parents ())
1136            { // may come from CMTPATH entry
1137              q->m_order = ++order;
1138              projs.push_back (q);
1139            }
1140        }
1141    }
1142
1143  visit (offset, order, projs);
1144
1145  int beg (0);
1146  if  (-1 != iuser)
1147    {
1148      OrderedProjects[0] = &(Projects[iuser]);
1149      //      cerr << "OrderedProjects[0]: " << (OrderedProjects[0])->get_name () << endl;
1150      ++beg;
1151    }
1152
1153  int noorder (0);
1154  for (int i = offset; i < size; i++)
1155    //  for (int i = 0; i < size; i++)
1156    {
1157      Project* p = &(Projects[i]);
1158      int j = p->m_order;
1159      if (-1 == j)
1160        {
1161          OrderedProjects[beg + order + 1 + noorder++] = p;
1162          //      cerr << "no: OrderedProjects[" << beg + order + noorder << "]: " << (OrderedProjects[beg + order + noorder])->get_name () << endl;
1163          //      OrderedProjects[order + 1 + noorder++] = p;
1164          /*
1165          if (CmtMessage::active (Verbose))
1166            CmtMessage::warning ("Not ordered project " + p->get_name () +
1167                                 " in path " + p->get_cmtpath_pwd () +
1168                                 " from " + p->get_cmtpath_source ());
1169          continue;
1170          */
1171        }
1172      else if (-2 != j)
1173        {
1174          OrderedProjects[beg + j] = p;
1175        }
1176      /*
1177      else if  (-2 == j)
1178        {
1179        }
1180      else
1181        {
1182          OrderedProjects[beg + j] = p;
1183      //      OrderedProjects[j] = p;
1184          //      cerr << "OrderedProjects[" << beg + j << "]: " << (OrderedProjects[beg + j])->get_name () << endl;
1185        }
1186      */
1187    }
1188
1189  if (p != 0)
1190    {
1191      for (int i = 0; i < noorder; i++)
1192        OrderedProjects.pop_back ();
1193    }
1194  if  (-1 != ihome)
1195    {
1196      OrderedProjects[OrderedProjects.size () - 1] = &(Projects[ihome]);
1197    }
1198  /*
1199  if (p)
1200    {
1201      if  (-1 != ihome)
1202        {
1203          OrderedProjects[beg + order + 1] = &(Projects[ihome]);
1204        }
1205      for (int i = 0; i < noorder; i++)
1206        OrderedProjects.pop_back ();
1207    }
1208  else
1209    {
1210      if  (-1 != ihome)
1211        {
1212          OrderedProjects[size - 1] = &(Projects[ihome]);
1213        }
1214    }
1215  */
1216      /*
1217  if  (-1 != iuser)
1218    {
1219      OrderedProjects[0]->add_child (OrderedProjects[1]);
1220      OrderedProjects[1]->add_parent (OrderedProjects[0]);
1221      OrderedProjects[0]->update_strategies_from_children ();
1222    }
1223      */
1224
1225//   if  (-1 != ihome)
1226//     {
1227      /*
1228      cerr << "beg: " << beg << " order: " << order << endl;
1229      cerr << "noorder: " << noorder << " size - offset: " << size - offset << endl;
1230      */
1231      /*
1232      if (noorder != size - offset)
1233        {  // the last ordered project
1234          OrderedProjects[beg + order]->add_child (OrderedProjects[size - 1]);
1235          OrderedProjects[size - 1]->add_parent (OrderedProjects[beg + order]);
1236          OrderedProjects[beg + order]->update_strategies_from_children ();
1237        }
1238      else
1239        {
1240          OrderedProjects[size - 2]->add_child (OrderedProjects[size - 1]);
1241          OrderedProjects[size - 1]->add_parent (OrderedProjects[size - 2]);
1242          OrderedProjects[size - 2]->update_strategies_from_children ();
1243        }
1244      */
1245//     }
1246
1247  for (int i = OrderedProjects.size () - 2; i >= 0; i--)
1248    {
1249      if (!OrderedProjects[i]->has_parents () &&
1250          OrderedProjects[i]->get_children_size () == 0)
1251        {
1252          OrderedProjects[i]->add_child (OrderedProjects[i + 1]);
1253          OrderedProjects[i]->update_strategies_from_children ();
1254          OrderedProjects[i]->erase_child (OrderedProjects[i + 1]);
1255        }
1256    }
1257
1258  orderedProjects = OrderedProjects;
1259  //  return OrderedProjects;
1260  return;
1261}
1262
1263/*----------------------------------------------------------*/
1264void Project::clear_all ()
1265{
1266  static ProjectVector& Projects = projects ();
1267
1268  for (int i = 0; i < Projects.size (); i++)
1269    {
1270      Project& project = Projects[i];
1271      project.clear ();
1272    }
1273
1274  Projects.clear ();
1275}
1276
1277/*----------------------------------------------------------*/
1278void Project::show_all (PrintMode mode)
1279//void Project::show_all ()
1280{
1281  static const Project::ProjectPtrVector& Ordered = Project::ordered_projects ();
1282  static Project::ProjectVector& Projects = Project::projects ();
1283 
1284  for (int i = 0; i < Projects.size (); i++)
1285    {
1286      Project& p = Projects[i];
1287      p.m_visited = false;
1288    }
1289
1290  switch (mode)
1291    {
1292    case Xml :
1293      Cmt::print_xml_prolog ("projects");
1294      cout << "<projects>";
1295      break;
1296    }
1297
1298  for (int i = 0; i < Ordered.size (); i++)
1299    Ordered[i]->show (mode);
1300  //    Ordered[i]->show ();
1301
1302  for (int i = 0; i < Projects.size (); i++)
1303    Projects[i].show (mode);
1304  //    Projects[i].show ();
1305
1306  switch (mode)
1307    {
1308    case Xml :
1309      cout << "</projects>" << endl;
1310      break;
1311    }
1312  /*
1313  Project* p = get_current ();
1314
1315  if (p == 0)
1316    {
1317      if (Ordered.size () == 0) return;
1318
1319      p = Ordered[0];
1320    }
1321  */
1322  //  p->show ();
1323}
1324
1325/*----------------------------------------------------------*/
1326void Project::show_container (const cmt_string& path)
1327//void Project::show_container ()
1328{
1329  Project* p (0);
1330  if (path == "")
1331    {
1332      p = get_current ();
1333    }
1334  else
1335    {
1336      p = find_by_cmtpath (find_in_cmt_paths (path));
1337    } 
1338
1339  if (p == 0)
1340    {
1341      cmt_string msg ("No project found for path "
1342                      + (path != "" ? path : (Use::current()).real_path)
1343                      );
1344      CmtMessage::warning (msg);
1345      CmtError::set (CmtError::warning, msg);
1346      return;
1347    }
1348  Use* use = &(p->m_container);
1349  if (use->get_package_name () == "")
1350    {
1351      cmt_string msg ("No container specified for project " + p->get_name ()
1352                      + " (" + p->get_cmtpath () + ")");
1353      CmtMessage::warning (msg);
1354      CmtError::set (CmtError::warning, msg);
1355      return;
1356    }
1357 
1358  if (!use->located ())
1359    {
1360      CmtMessage::warning ("container " + use->get_info ()
1361                           + " not found");
1362      CmtError::set (CmtError::package_not_found, use->get_package_name ());
1363    }
1364  else
1365    {
1366      static const cmt_string empty;
1367      cmt_string p = use->real_path;
1368      if (use->path != "")
1369        {
1370          int pos = p.find_last_of (use->path);
1371          if (pos != cmt_string::npos)
1372            {
1373              p.erase (pos);
1374            }
1375        }
1376     
1377      cout << "container " << use->get_package_name ()
1378           << " " << use->version;
1379     
1380      if (CmtSystem::absolute_path (use->path))
1381        {
1382          if (!Cmt::get_quiet ()) 
1383            {
1384              cout << " (" << use->path << ")";
1385            }
1386        }
1387      else
1388        {
1389          cout << " " << use->path;
1390        }
1391     
1392      if (!Cmt::get_quiet ()) 
1393        {
1394          if (p != "") cout << " (" << p << ")";
1395          if (use->auto_imports == Off) cout << " (no_auto_imports)";
1396        }
1397     
1398      cout << endl;
1399    }
1400}
1401
1402/*----------------------------------------------------------*/
1403void Project::show_specified_strategies_for_all ()
1404{
1405  static ProjectVector& Projects = projects ();
1406
1407  for (int i = 0; i < Projects.size (); i++)
1408    {
1409      const Project& project = Projects[i];
1410      project.show_specified_strategies ();
1411    }
1412}
1413
1414/*----------------------------------------------------------*/
1415class VisitorForShowPaths : public IProjectVisitor
1416{
1417public:
1418  VisitorForShowPaths ()
1419  {
1420  }
1421
1422  void pre (Project* p)
1423  {
1424    const cmt_string& w = p->get_cmtpath_pwd ();
1425    const cmt_string& s = p->get_cmtpath_source ();
1426
1427    if (s == "default path") return;
1428
1429    if (CmtSystem::test_directory (w))
1430      {
1431        cout << "# Add path " << w << " from " << s << endl;
1432      }
1433  }
1434
1435  void in (Project* p)
1436  {
1437    const cmt_string& w = p->get_cmtpath_pwd ();
1438    const cmt_string& s = p->get_cmtpath_source ();
1439
1440    if (s == "default path") return;
1441
1442    if (CmtSystem::test_directory (w))
1443      {
1444        cout << "# Add path " << w << " from " << s << endl;
1445      }
1446  }
1447
1448  void in_again (Project* p)
1449  {
1450    const cmt_string& w = p->get_cmtpath_pwd ();
1451    const cmt_string& s = p->get_cmtpath_source ();
1452
1453    if (s == "default path") return;
1454
1455    if (CmtSystem::test_directory (w))
1456      {
1457        cout << "# Remove path " << w << " from " << s << endl;
1458        cout << "# Add path " << w << " from " << s << endl;
1459      }
1460  }
1461
1462  void post (Project* p)
1463  {
1464  }
1465};
1466
1467/*----------------------------------------------------------*/
1468void Project::show_paths (const CmtSystem::cmt_string_vector& arguments,
1469                          ostream& out)
1470//void Project::show_paths ()
1471{
1472  if (arguments.size () == 0 ||
1473      Cmt::get_action () != action_show_path)
1474    {
1475      const ProjectPtrVector& Ordered = Project::ordered_projects ();
1476      for (int i = 0; i < Ordered.size (); i++)
1477        {
1478          const Project* p = Ordered[i];
1479          const cmt_string& w = p->get_cmtpath_pwd ();
1480          const cmt_string& s = p->get_cmtpath_source ();
1481         
1482          if (s == "default path") continue;
1483         
1484          if (CmtSystem::test_directory (w))
1485            {
1486              out << "# Add path " << w << " from " << s << endl;
1487            }
1488        }
1489    }
1490  else if (arguments.size () == 1 && cmt_string (arguments[0]) == "-d")
1491    {
1492      const ProjectVector& Projects = projects ();
1493      for (int i = 0; i < Projects.size (); i++)
1494        {
1495          Project& p = Projects[i];
1496          const cmt_string& w = p.get_cmtpath_pwd ();
1497          const cmt_string& s = p.get_cmtpath_source ();
1498         
1499          if (s == "default path") continue;
1500         
1501          if (CmtSystem::test_directory (w))
1502            {
1503              out << "# Create path " << w << " from " << s << endl;
1504            }
1505        }
1506      /*
1507      VisitorForShowPaths visitor;
1508      start_visit (visitor);
1509      */
1510    }
1511  else
1512    CmtMessage::error ("show_paths: unexpected argument(s)");
1513}
1514
1515//----------------------------------------------------------
1516const cmt_string& Project::get_project_file_name ()
1517{
1518  static const cmt_string name = "project.cmt";
1519
1520  return (name);
1521}
1522
1523//----------------------------------------------------------
1524/**
1525 *  Fill with projects (pointers) for CMTPATH entries >=1 and <= depth
1526 *  except for CMTUSERCONTEXT project or CMTHOME project
1527 *  unless either is current project.
1528 *  Special values of depth:
1529 *   0: CMTUSERCONTEXT project only
1530 *  -1: CMTHOME project only
1531 *
1532 *  @param depth in CMTPATH up to which fill
1533 *  @param path_selections vector to fill
1534 */
1535void Project::fill_selection (int depth, ConstProjectPtrVector& path_selections)
1536{
1537  static ProjectPtrVector& Ordered = Project::ordered_projects ();
1538  int curdepth = depth;
1539  for (int i = 0; i < Ordered.size (); i++)
1540    {
1541      const Project* project = Ordered[i];
1542      const cmt_string& src = project->get_cmtpath_source ();
1543
1544      if (src == "default path") continue;
1545
1546      if (depth > 0)
1547        {
1548          // project for CMTPATH entries >=1 and <= depth
1549          // except for CMTUSERCONTEXT path or CMTHOME path
1550          // OR
1551          // CMTUSERCONTEXT path if it's current project
1552          // CMTHOME        path if it's current project
1553          if (i == 0
1554              && !project->is_current ()
1555              && src == "CMTUSERCONTEXT") continue;
1556          // this is CMTUSERCONTEXT
1557          if (i == Ordered.size () - 1
1558              && !project->is_current ()
1559              && src == "CMTHOME") continue;
1560          // this is CMTHOME
1561          path_selections.push_back (project);
1562          //cerr << "fill: " << i << ": " << project->get_cmtpath () << ": " << curdepth << endl;
1563          if (--curdepth == 0) break;
1564        }
1565      else if (depth == 0)
1566        {
1567          // CMTUSERCONTEXT path only
1568          if (i == 0
1569              && src == "CMTUSERCONTEXT")
1570            {
1571              path_selections.push_back (project);
1572              break;
1573            }
1574        }
1575      else if (depth == -1)
1576        {
1577          // CMTHOME path only
1578          if (i == Ordered.size () - 1
1579              && src == "CMTHOME")
1580            {
1581              path_selections.push_back (project);
1582              break;
1583            }
1584        }
1585    }
1586}
1587
1588//----------------------------------------------------------
1589// void Project::fill_selection (int depth, CmtSystem::cmt_string_vector& path_selections)
1590// {
1591//   static ProjectPtrVector& Ordered = Project::ordered_projects ();
1592//   int curdepth = depth;
1593//   for (int i = 0; i < Ordered.size (); i++)
1594//     {
1595//       const Project* project = Ordered[i];
1596
1597//       const cmt_string& p = project->get_cmtpath ();
1598//       const cmt_string& pwd = project->get_cmtpath_pwd ();
1599//       const cmt_string& p_real = project->get_cmtpath_real ();
1600//       const cmt_string& src = project->get_cmtpath_source ();
1601
1602//       if (src == "default path") continue;
1603
1604//       if (depth > 0)
1605//      {
1606//        // packages from CMTPATH entries >=1 and <= depth
1607//        // except for CMTUSERCONTEXT path or CMTHOME path
1608//        // OR
1609//        // CMTUSERCONTEXT path if it's current project
1610//        // CMTHOME        path if it's current project
1611//        if (i == 0
1612//            && !project->is_current ()
1613//            && src == "CMTUSERCONTEXT") continue;
1614//        // this is CMTUSERCONTEXT
1615//        if (i = Ordered.size () - 1
1616//            && !project->is_current ()
1617//            && src == "CMTHOME") continue;
1618//        // this is CMTHOME
1619//        cmt_string& s1 = path_selections.add ();
1620//        s1 = p;
1621//        if (pwd != p)
1622//          {
1623//            cmt_string& s2 = path_selections.add ();
1624//            s2 = pwd;
1625//          }
1626//        if (p_real != p && p_real != pwd)
1627//          {
1628//            cmt_string& s3 = path_selections.add ();
1629//            s3 = p_real;
1630//          }
1631//        if (--curdepth == 0) break;
1632//      }
1633//       else if (depth == 0)
1634//      {
1635//        // CMTUSERCONTEXT path only
1636//        if (i == 0
1637//            && src == "CMTUSERCONTEXT")
1638//          {
1639//            cmt_string& s1 = path_selections.add ();
1640//            s1 = p;
1641//            if (pwd != p)
1642//              {
1643//                cmt_string& s2 = path_selections.add ();
1644//                s2 = pwd;
1645//              }
1646//            if (p_real != p && p_real != pwd)
1647//              {
1648//                cmt_string& s3 = path_selections.add ();
1649//                s3 = p_real;
1650//              }
1651//            break;
1652//          }
1653//      }
1654//       else if (depth == -1)
1655//      {
1656//        // CMTHOME path only
1657//        if (i = Ordered.size () - 1
1658//            && src == "CMTHOME")
1659//          {
1660//            cmt_string& s1 = path_selections.add ();
1661//            s1 = p;
1662//            if (pwd != p)
1663//              {
1664//                cmt_string& s2 = path_selections.add ();
1665//                s2 = pwd;
1666//              }
1667//            if (p_real != p && p_real != pwd)
1668//              {
1669//                cmt_string& s3 = path_selections.add ();
1670//                s3 = p_real;
1671//              }
1672//            break;
1673//          }
1674//      }
1675// //     if (depth > 0)
1676// //       {
1677// //         cmt_string& s1 = path_selections.add ();
1678// //         s1 = p;
1679// //         if (pwd != p)
1680// //           {
1681// //             cmt_string& s2 = path_selections.add ();
1682// //             s2 = pwd;
1683// //           }
1684// //         if (p_real != p && p_real != pwd)
1685// //           {
1686// //             cmt_string& s3 = path_selections.add ();
1687// //             s3 = p_real;
1688// //           }
1689// //         if (src != "CMTHOME" && src != "CMTUSERCONTEXT")
1690// //           depth--;
1691
1692// //         if (depth == 0) break;
1693// //       }
1694
1695//     }
1696// }
1697
1698//----------------------------------------------------------
1699/**
1700 *  Fill with projects (pointers) for CMTUSERCONTEXT and CMTHOME projects
1701 *  (if any exists)
1702 *  unless either is current project.
1703 * 
1704 *  @param path_exclusions vector to fill
1705 */
1706void Project::fill_exclusion (ConstProjectPtrVector& path_exclusions)
1707{
1708  static ProjectPtrVector& Ordered = Project::ordered_projects ();
1709  for (int i = 0; i < Ordered.size (); i++)
1710    {
1711      const Project* project = Ordered[i];
1712      const cmt_string& src = project->get_cmtpath_source ();
1713
1714      if (!project->is_current ()
1715          && (src == "CMTUSERCONTEXT" || src == "CMTHOME"))
1716        path_exclusions.push_back (project);
1717    }
1718}
1719
1720//----------------------------------------------------------
1721void Project::broadcast (IProjectAction& action)
1722{
1723  //  const ProjectPtrVector Projects = Project::ordered_projects ();
1724  static ProjectPtrVector& Projects = Project::ordered_projects ();
1725
1726  for (int i = 0; i < Projects.size (); i++)
1727    {
1728      const Project* project = Projects[i];
1729
1730      if (!action.run (*project)) break;
1731    }
1732  /*
1733  static ProjectVector& Projects = projects ();
1734
1735  for (int i = 0; i < Projects.size (); i++)
1736    {
1737      const Project& project = Projects[i];
1738
1739      if (!action.run (project)) break;
1740    }
1741  */
1742}
1743
1744//----------------------------------------------------------
1745void Project::reverse_broadcast (IProjectAction& action)
1746{
1747  //  const ProjectPtrVector Projects = Project::ordered_projects ();
1748  static ProjectPtrVector& Projects = Project::ordered_projects ();
1749
1750  for (int i = (Projects.size () - 1); i >= 0; i--)
1751    {
1752      const Project* project = Projects[i];
1753
1754      if (!action.run (*project)) break;
1755    }
1756  /*
1757  static ProjectVector& Projects = projects ();
1758
1759  for (int i = (Projects.size () - 1); i >= 0; i--)
1760    {
1761      const Project& project = Projects[i];
1762
1763      if (!action.run (project)) break;
1764    }
1765  */
1766}
1767
1768//----------------------------------------------------------
1769void Project::scan_paths (PathScanner& scanner, PathScanner::actor& a)
1770{
1771  static ProjectVector& Projects = projects ();
1772
1773  int i;
1774
1775  for (i = 0; i < Projects.size (); i++)
1776    {
1777      Project& p  = Projects[i];
1778      p.m_visited = false;
1779    }
1780
1781  for (i = 0; i < Projects.size (); i++)
1782    {
1783      const Project& project = Projects[i];
1784       
1785      const cmt_string& p = project.m_cmtpath;
1786      scanner.scan_path (p, a);
1787    }
1788}
1789
1790//----------------------------------------------------------
1791void Project::scan_paths_for_package (PathScanner& scanner, const cmt_string& name)
1792{
1793  static ProjectVector& Projects = projects ();
1794
1795  bool found (false);
1796  for (int i = 0; i < Projects.size (); i++)
1797    {
1798      const Project& project = Projects[i];
1799
1800      const cmt_string& p = project.m_cmtpath;
1801      if (scanner.scan_package (p, name))
1802        found = true;
1803    }
1804
1805  if (!found)
1806    CmtError::set (CmtError::package_not_found, name);
1807}
1808
1809//----------------------------------------------------------
1810cmt_string Project::find_in_cmt_paths (const cmt_string& path, bool realpath)
1811{
1812  //const cmt_string pwd = CmtSystem::pwd ();
1813
1814  // In case there are symlinks
1815  cmt_string path_real;
1816  //cerr << "realpath_: find_in_cmt_paths" << endl;
1817  if (realpath)
1818    path_real = path;
1819  else if (!CmtSystem::realpath_ (path, path_real))
1820    return ("");
1821
1822  static ProjectVector& Projects = projects ();
1823
1824  for (int i = 0; i < Projects.size (); i++)
1825    {
1826      const Project& project = Projects[i];
1827
1828      const cmt_string& p = project.m_cmtpath;
1829      const cmt_string& p_real = project.m_cmtpath_real;
1830      const cmt_string& w = project.m_cmtpath_pwd;
1831      const cmt_string& s = project.m_cmtpath_source;
1832
1833      if (s == "default path") continue;
1834
1835      // MUST be directory if project added
1836      //      if (CmtSystem::test_directory (p))
1837        {
1838//        if (path.find (p) != cmt_string::npos)
1839//          {
1840//            return (p);
1841//          }
1842
1843          if (path_real.find (p_real) == 0) //!= cmt_string::npos)
1844            {
1845              return (p);
1846            }
1847
1848          // To become the current area, a path must correspond to the current package
1849          if (path.find (w) == 0)// != cmt_string::npos)
1850            {
1851              return (p);
1852            }
1853        }
1854
1855        /* This code is never used since p is returned above
1856      if (p == w) continue;
1857
1858      // MUST be directory if project added
1859      //      if (CmtSystem::test_directory (w))
1860        {
1861          if (path.find (w) == 0)// != cmt_string::npos)
1862            {
1863              return (w);
1864            }
1865        }
1866        */
1867    }
1868
1869  return ("");
1870}
1871
1872//----------------------------------------------------------
1873void Project::visit (IProjectVisitor& visitor)
1874{
1875  if (m_visited) return;
1876  m_visited = true;
1877
1878  int i;
1879
1880  for (i = 0; i < get_children_size (); i++)
1881    {
1882      Project* child = get_child (i);
1883
1884      if (child->visited ()) continue;
1885
1886      visitor.in (child);
1887    }
1888
1889  for (i = 0; i < m_children.size (); i++)
1890    {
1891      Project* child = m_children[i];
1892      child->visit (visitor);
1893    }
1894}
1895
1896//----------------------------------------------------------
1897void Project::visit (IProjectVisitor& visitor, ProjectPtrVector& projects)
1898{
1899  int size = projects.size ();
1900  if (0 == size) return;
1901
1902  ProjectPtrVector children;
1903  for (int j = 0; j < size; j++)
1904    {
1905      Project* p = projects[j];
1906      if (20 == p->m_visits)
1907        continue;
1908      for (int i = 0; i < p->get_children_size (); i++)
1909        {
1910          Project* child = p->get_child (i);
1911          if (0 == child->m_visits)       
1912            visitor.in (child);
1913          else
1914            visitor.in_again (child);
1915          child->m_visits++;
1916          children.push_back (child);
1917        }
1918    }
1919
1920  visit (visitor, children);
1921}
1922
1923//----------------------------------------------------------
1924/**
1925 *  Visit the projects tree and order the projects.
1926 *  Order is the projects upon which the project depends directly,
1927 *  then the direct dependencies of the of the first dependency, of the second
1928 *  dependency and so on. That is first left to right, then downwards.
1929 *  @param offset the offset from which to use all the projects
1930 *  @param order the order of the last project visited
1931 *  @param projs vector of projects to visit and order
1932 */
1933void Project::visit (const int offset, int& order, ProjectPtrVector& projs)
1934{
1935  int size = projs.size ();
1936  //  cerr << "visit: " << offset << " " << order << " " << size << endl;
1937  if (0 == size) return;
1938  static ProjectVector& all = Project::projects ();
1939  /*
1940  cerr << "@ visit: " << order;
1941  for (int j = 0; j < size; j++)
1942    {
1943      Project* p = projs[j];
1944      cerr << " " << p->get_name ();
1945    }
1946  cerr << " @" << endl;
1947  */
1948  ProjectPtrVector children;
1949  for (int j = 0; j < size; j++)
1950    {
1951      Project* p = projs[j];
1952      p->m_visits++;
1953      // Avoid looping in case of circular project dependencies
1954      if (500 <= p->m_visits)
1955        //      if (100 <= p->m_visits)
1956        continue;
1957      for (int i = 0; i < p->get_children_size (); i++)
1958        {
1959          Project* child = p->get_child (i);
1960          const int chorder = child->m_order;
1961          const int porder = p->m_order;
1962          /*
1963          cerr << ">>> " << p->get_name () << " child: " << i << endl;
1964          cerr << child->get_name () << " in: " << chorder << endl;
1965          */
1966          if (-2 == chorder)
1967            continue;
1968          else if (-1 == chorder)
1969            { // not ordered yet, i.e. visited for the first time
1970              child->m_order = ++order;
1971            }
1972          else if (child->is_current ())
1973            //    else if (0 == chorder)
1974            { // the project we started with, i. e. the current project:
1975              //     o circular dependency
1976              //     o do want to keep it first no matter what
1977              if (CmtMessage::active (Verbose))
1978                CmtMessage::warning ("Circular dependency on project: "
1979                                     + child->get_name ()
1980                                     + " " + child->get_release ()
1981                                     + " " + child->get_cmtpath ());
1982            }
1983          else if ((0 <= chorder) && (chorder < porder))
1984            //    else if ((0 < chorder) && (chorder < porder))
1985            { // ordered already, want to put it after the parent in the order
1986              for (int k = offset; k < all.size (); k++)
1987                {
1988                  Project& q = all[k];
1989                  if (&q == child)
1990                    {// the child we are putting after the parent in the order
1991                      q.m_order = porder;
1992                      //              cerr << "Moved back: " << q.get_name () << " order: " << q.m_order << endl;
1993                    }
1994                  else if ((chorder < q.m_order) && (q.m_order <= porder))
1995                    q.m_order--;
1996                }
1997            }
1998          //  cerr << child->get_name () << " out: " << child->m_order << endl;
1999          //      child->m_visits++;
2000          bool unknown (true);
2001          for (int j = 0; j < children.size (); j++)
2002            {
2003              if (children[j] == child)
2004                {
2005                  unknown = false;
2006                  break;
2007                }
2008            }
2009          if (unknown)
2010            {
2011              children.push_back (child);
2012            }
2013        }
2014    }
2015
2016  visit (offset, order, children);
2017}
2018
2019//----------------------------------------------------------
2020void Project::start_visit (IProjectVisitor& visitor)
2021{
2022  static Project::ProjectVector& Projects = Project::projects ();
2023 
2024  for (int i = 0; i < Projects.size (); i++)
2025    {
2026      Project& p = Projects[i];
2027      p.m_visited = false;
2028      p.m_visits = 0;
2029    }
2030
2031  Project* p = get_current ();
2032
2033  if (p == 0)
2034    {
2035      if (Projects.size () == 0) return;
2036
2037      p = &(Projects[0]);
2038    }
2039
2040  //  visitor.pre (p);
2041  //p->visit (visitor);
2042  //  visitor.post (p);
2043  visitor.in (p);
2044  p->m_visits++;
2045  ProjectPtrVector projs;
2046  projs.push_back (p);
2047  visit (visitor, projs);
2048}
2049
2050//----------------------------------------------------------
2051class VisitorForFillCMTPATH : public IProjectVisitor
2052{
2053public:
2054  VisitorForFillCMTPATH (cmt_string& buffer) : m_buffer (buffer)
2055  {
2056    buffer = "path CMTPATH \"\" \n";
2057  }
2058
2059  void pre (Project* p)
2060  {
2061    const cmt_string& w = p->get_cmtpath_pwd ();
2062    const cmt_string& s = p->get_cmtpath_source ();
2063
2064    if (s == "default path") return;
2065
2066    if (CmtSystem::test_directory (w))
2067      {
2068        m_buffer += "path_append CMTPATH \"";
2069        m_buffer += w;
2070        m_buffer += "\" \n";
2071      }
2072  }
2073
2074  void in (Project* p)
2075  {
2076    const cmt_string& w = p->get_cmtpath_pwd ();
2077    const cmt_string& s = p->get_cmtpath_source ();
2078
2079    if (s == "default path") return;
2080
2081    if (CmtSystem::test_directory (w))
2082      {
2083        m_buffer += "path_append CMTPATH \"";
2084        m_buffer += w;
2085        m_buffer += "\" \n";
2086      }
2087  }
2088
2089  void in_again (Project* p)
2090  {
2091    const cmt_string& w = p->get_cmtpath_pwd ();
2092    const cmt_string& s = p->get_cmtpath_source ();
2093
2094    if (s == "default path") return;
2095
2096    if (CmtSystem::test_directory (w))
2097      {
2098        m_buffer += "path_remove CMTPATH \"";
2099        m_buffer += w;
2100        m_buffer += "\" \n";
2101        m_buffer += "path_append CMTPATH \"";
2102        m_buffer += w;
2103        m_buffer += "\" \n";
2104      }
2105  }
2106
2107  void post (Project* p)
2108  {
2109    //cerr << "Buffer = " << m_buffer << endl;
2110  }
2111
2112private:
2113  cmt_string& m_buffer;
2114
2115};
2116
2117//----------------------------------------------------------
2118void Project::fill_cmtpaths (cmt_string& buffer)
2119{
2120  /*
2121    Try to re-create all CMTPATH items from project definitions.
2122    The goal is to generate CMTPATH even if this EV was not pre-set
2123    which is the case when CMTPROJECTPATH is only used
2124  */
2125
2126  /*
2127  VisitorForFillCMTPATH visitor (buffer);
2128
2129  start_visit (visitor);
2130  */
2131  const ProjectPtrVector& Ordered = Project::ordered_projects ();
2132
2133  buffer = "path CMTPATH \"\" \n";
2134  for (int i = 0; i < Ordered.size (); i++)
2135    {
2136      const Project* p = Ordered[i];
2137      const cmt_string& w = p->get_cmtpath_pwd ();
2138      const cmt_string& s = p->get_cmtpath_source ();
2139     
2140      if (s == "default path") continue;
2141     
2142      if (CmtSystem::test_directory (w))
2143        {
2144          buffer += "path_append CMTPATH \"";
2145          buffer += w;
2146          buffer += "\" \n";
2147        }
2148    }
2149}
2150
2151//----------------------------------------------------------
2152Project::Project () : m_name (""), m_author("")
2153{
2154  clear ();
2155}
2156
2157//----------------------------------------------------------
2158const cmt_string& Project::get_name () const
2159{
2160  return (m_name);
2161}
2162
2163//----------------------------------------------------------
2164const cmt_string& Project::get_release () const
2165{
2166  return (m_release);
2167}
2168
2169//----------------------------------------------------------
2170const cmt_string& Project::get_container_name () const
2171{
2172  return (m_container_name);
2173}
2174
2175//----------------------------------------------------------
2176const cmt_string& Project::get_container_version () const
2177{
2178  return (m_container_version);
2179}
2180
2181//----------------------------------------------------------
2182const cmt_string& Project::get_container_path () const
2183{
2184  return (m_container_path);
2185}
2186
2187//----------------------------------------------------------
2188const Use& Project::get_container () const
2189{
2190  return (m_container);
2191}
2192
2193//----------------------------------------------------------
2194const cmt_string& Project::get_cmtpath () const
2195{
2196  return (m_cmtpath);
2197}
2198
2199//----------------------------------------------------------
2200const cmt_string& Project::get_cmtpath_real () const
2201{
2202  return (m_cmtpath_real);
2203}
2204
2205//----------------------------------------------------------
2206const cmt_string& Project::get_cmtpath_pwd () const
2207{
2208  return (m_cmtpath_pwd);
2209}
2210
2211//----------------------------------------------------------
2212const cmt_string& Project::get_cmtpath_source () const
2213{
2214  return (m_cmtpath_source);
2215}
2216
2217//----------------------------------------------------------
2218int Project::get_children_size () const
2219{
2220  return (m_children.size ());
2221}
2222
2223//----------------------------------------------------------
2224Project* Project::get_child (int index) const
2225{
2226  if (index < 0) return (0);
2227  if (index >= m_children.size ()) return (0);
2228  return (m_children[index]);
2229}
2230
2231//----------------------------------------------------------
2232bool Project::visited () const
2233{
2234  return (m_visited);
2235}
2236
2237//----------------------------------------------------------
2238void Project::set_name (const cmt_string& name)
2239{
2240  m_name = name;
2241}
2242
2243//----------------------------------------------------------
2244void Project::set_release (const cmt_string& release)
2245{
2246  m_release = release;
2247}
2248
2249//----------------------------------------------------------
2250void Project::set_container_name (const cmt_string& name)
2251{
2252  m_container_name = name;
2253}
2254
2255//----------------------------------------------------------
2256void Project::set_container_version (const cmt_string& container_version)
2257{
2258  m_container_version = container_version;
2259}
2260
2261//----------------------------------------------------------
2262void Project::set_container_path (const cmt_string& container_path)
2263{
2264  m_container_path = container_path;
2265}
2266
2267//----------------------------------------------------------
2268void Project::set_cmtpath (const cmt_string& path)
2269{
2270  m_cmtpath = path;
2271}
2272
2273//----------------------------------------------------------
2274void Project::set_cmtpath_real (const cmt_string& path)
2275{
2276  m_cmtpath_real = path;
2277}
2278
2279//----------------------------------------------------------
2280void Project::set_cmtpath_pwd (const cmt_string& path)
2281{
2282  m_cmtpath_pwd = path;
2283}
2284
2285//----------------------------------------------------------
2286void Project::set_cmtpath_source (const cmt_string& source)
2287{
2288  m_cmtpath_source = source;
2289}
2290
2291//----------------------------------------------------------
2292void Project::set_is_current (bool is_current)
2293{
2294  m_is_current = is_current;
2295}
2296
2297//----------------------------------------------------------
2298bool Project::is_current () const
2299{
2300  return m_is_current;
2301}
2302
2303//----------------------------------------------------------
2304void Project::clear ()
2305{
2306  m_name    = "";
2307  m_release = "";
2308  m_cmtpath = "";
2309  m_cmtpath_real = "";
2310  m_cmtpath_pwd    = "";
2311  m_cmtpath_source = "";
2312  m_use            = 0;
2313
2314  m_parents.clear ();
2315  m_children.clear ();
2316
2317  m_configured = false;
2318
2319  m_strategies.clear ();
2320  m_is_current = false;
2321}
2322
2323//----------------------------------------------------------
2324bool Project::has_parents () const
2325{
2326  return ((m_parents.size () > 0));
2327}
2328
2329//----------------------------------------------------------
2330bool Project::has_parent (Project* p) const
2331{
2332  if (p == 0) return (false);
2333  if (p == this) return (false);
2334
2335  const cmt_string& name = p->get_name ();
2336
2337  int i;
2338
2339  for (i = 0; i < m_parents.size (); i++)
2340    {
2341      const Project* parent = m_parents[i];
2342      if (parent == 0) continue;
2343
2344      if (parent->get_name () == name)
2345        {
2346          // registered as a parent
2347          return (true);
2348        }
2349
2350      if (parent->has_parent (p))
2351        {
2352          // recurse
2353          return (true);
2354        }
2355    }
2356
2357  return (false);
2358}
2359
2360//----------------------------------------------------------
2361bool Project::has_child (Project* p) const
2362{
2363  if (p == 0) return (false);
2364  if (p == this) return (false);
2365
2366  const cmt_string& name = p->get_name ();
2367
2368  int i;
2369
2370  for (i = 0; i < m_children.size (); i++)
2371    {
2372      const Project* child = m_children[i];
2373      if (child == 0) continue;
2374
2375      if (child->get_name () == name)
2376        {
2377          // registered as a child
2378          return (true);
2379        }
2380
2381      if (child->has_child (p))
2382        {
2383          // recurse
2384          return (true);
2385        }
2386    }
2387
2388  return (false);
2389}
2390
2391//----------------------------------------------------------
2392void Project::add_parent (Project* p)
2393{
2394  if (p == 0) return;
2395  if (p == this) return;
2396
2397  //cerr << "Adding parent " << p->get_name () << " to " << m_name << endl;
2398
2399  if (has_child (p)) return;
2400  if (has_parent (p)) return;
2401
2402  m_parents.push_back (p);
2403}
2404
2405//----------------------------------------------------------
2406void Project::add_child (Project* p)
2407{
2408  if (p == 0) return;
2409  if (p == this) return;
2410
2411  if (has_child (p)) return;
2412  if (has_parent (p)) return;
2413
2414  m_children.push_back (p);
2415}
2416
2417//----------------------------------------------------------
2418void Project::erase_child (Project* p)
2419{
2420  if (p == 0) return;
2421  if (p == this) return;
2422
2423  if (!has_child (p)) return;
2424
2425  const cmt_string& name = p->get_name ();
2426
2427  for (int i = 0; i < m_children.size (); i++)
2428    {
2429      const Project* child = m_children[i];
2430      if (child == 0) continue;
2431
2432      if (child->get_name () == name)
2433        {
2434          // registered as a child
2435          m_children.erase (i);
2436          break;
2437        }
2438    }
2439}
2440
2441//----------------------------------------------------------
2442void Project::configure ()
2443{
2444  if (m_configured) return;
2445  m_configured = true;
2446
2447  set_default_strategy ("SetupConfig");
2448  set_default_strategy ("SetupRoot");
2449  set_default_strategy ("SetupCleanup");
2450  set_default_strategy ("SetupScripts");
2451  set_default_strategy ("BuildPrototypes");
2452  set_default_strategy ("InstallArea");
2453  set_default_strategy ("VersionDirectory");
2454}
2455
2456/**---------------------------------------------------------
2457   A container statement is met in the project file
2458*/
2459void Project::container_action (const CmtSystem::cmt_string_vector& words)
2460//void Project::container_action (const cmt_string& name, const cmt_string& version)
2461{
2462  //
2463  // complete syntax : "container <package> <version> <path>" 
2464  // minimal syntax  : "container <package>"
2465  //
2466  //  o if <version> is omitted then take any version available
2467  //  o <version> can be specified using "v*" or "v<n>r*" or "v<n>r<m>p*"
2468  //
2469  //  o the notation "v*" is preferred to omission (particularly since
2470  //    omission does not permit <path>)
2471  //
2472  if (words.size () < 2) return;
2473
2474  CmtSystem::cmt_string_vector ewords;
2475  for (int i = 1; i < words.size (); i++)
2476    {
2477      const cmt_string& w = words[i];
2478      cmt_string ew = w;
2479
2480      Symbol::expand (ew);
2481      if (ew != w)
2482        {
2483          CmtSystem::cmt_string_vector ws;
2484          CmtSystem::split (ew, " ", ws);
2485
2486          for (int j = 0; j < ws.size (); ++j)
2487            {
2488              ewords.push_back (ws[j]);
2489            }
2490        }
2491      else
2492        {
2493          ewords.push_back (w);
2494        }
2495    }
2496
2497  cmt_string name, version, path;
2498  if (ewords.size () > 0) name = ewords[0];
2499  if (ewords.size () > 1) version = ewords[1];
2500  if (ewords.size () > 2) path = ewords[2];
2501
2502  Use* use = &m_container;
2503  if (name == "")
2504    {
2505      use->clear ();
2506      return;
2507    }
2508  if (version == "") version = "*";
2509
2510  use->set (name, version, path);
2511  use->get_package ()->remove_use (use);
2512  CmtSystem::cd (m_cmtpath_pwd);
2513  if (use->move_to ("", true))
2514    {
2515      if (use->get_realpath ().find (this->get_cmtpath_real ()) == 0)
2516        use->set_project (this);
2517    }
2518  else
2519    if (0 == CmtSystem::getenv ("CMTPEDANTIC").size () &&
2520        0 == CmtSystem::getenv ("PEDANTIC").size ())
2521      CmtMessage::warning
2522        (CmtError::get_error_name (CmtError::configuration_error)
2523         + ": Cannot locate container: " + use->get_info ());
2524    else
2525      CmtError::set(CmtError::configuration_error,
2526                    "Cannot locate container: " + use->get_info ());
2527 
2528  CmtSystem::cd (m_cmtpath_pwd + CmtSystem::file_separator () + "cmt");
2529
2530  if (CmtError::get_last_error_code () == CmtError::configuration_error)
2531    return;
2532
2533  set_container_name (name);
2534  set_container_version (version);
2535  set_container_path (path);
2536}
2537
2538/**---------------------------------------------------------
2539   A use statement is met in the project file
2540*/
2541void Project::use_action (const cmt_string& name, const cmt_string& release)
2542{
2543  if (Cmt::get_debug ())
2544    {
2545      cout << "Use action " << name << " " << release << endl;
2546    }
2547
2548  // A project with its release is specified
2549  //
2550  // Is this project already visible?
2551  // If not: look for it
2552  //   + get CMTPROJECTPATH
2553  //   + search from all entries of CMTPROJECTPATH : p(i)/<name>/<release>
2554  //   + when found, this should become a new CMTPATH entry
2555  //   +             the new project is then parsed ... etc...
2556
2557  // First test it wilcard is used
2558  int v = -1;
2559  int r = -1;
2560  int p = -1;
2561  cmt_string new_release = release;
2562  CmtSystem::is_version_directory (new_release, v, r, p); 
2563  bool use_has_wild_card = (v == -1) || (r == -1) || (p == -1);
2564  if (use_has_wild_card)
2565    {
2566      cmt_string selected_release = "";
2567
2568      if (select_release(name, new_release,selected_release))
2569        {
2570          // cerr <<"selected_release: "<<selected_release<<endl;   
2571          new_release = selected_release;
2572        }         
2573    }
2574
2575  cmt_string cmtprojectpath = Symbol::get_env_value ("CMTPROJECTPATH");
2576  cmt_string sep;
2577  sep = CmtSystem::path_separator ();
2578
2579  CmtSystem::cmt_string_vector items;
2580  CmtSystem::split (cmtprojectpath, sep, items);
2581
2582  bool found = false;
2583
2584  for (int i = 0; i < items.size (); i++)
2585    {
2586      const cmt_string& item = items[i];
2587      cmt_string p = item;
2588      p += CmtSystem::file_separator ();
2589      p += name;
2590      if (new_release != "")
2591        {
2592          p += CmtSystem::file_separator ();
2593          p += new_release;
2594        }
2595
2596      if (CmtSystem::test_directory (p))
2597        {
2598          //cerr << "Project directory " << p << " exists " << endl;
2599
2600          found = true;
2601
2602          IProjectFactory& factory = ProjectFactory::instance ();
2603
2604          factory.create_project (name, p, "ProjectPath", this);
2605
2606          break;
2607        }
2608    }
2609
2610  if (!found)
2611    {
2612      Project* p = Project::find_by_name (name);
2613
2614      if (p != 0)
2615        {
2616          found = true;
2617          p->add_parent (this);
2618          add_child (p);
2619
2620          update_strategies_from_children ();
2621        }
2622    }
2623   
2624  if (!found && (cmtprojectpath != ""))
2625    {
2626      CmtMessage::warning ("Project " + name + " " + release + " requested by " + m_name + " not found in CMTPROJECTPATH");
2627      //      cerr << "#CMT> Project " << name << " " << release << " requested by " << m_name << " not found in CMTPROJECTPATH" << endl;
2628    }
2629}
2630
2631//---------------------------------------------------------
2632bool Project::select_release(const cmt_string& name, const cmt_string& release, cmt_string& result)
2633{
2634  cmt_string selected_release = "";
2635
2636  int v = -1;
2637  int r = -1;
2638  int p = -1;
2639  CmtSystem::is_version_directory (release, v, r, p); 
2640
2641  int selected_v = -1;
2642  int selected_r = -1;
2643  int selected_p = -1;
2644  CmtSystem::cmt_string_vector releases = get_project_releases(name);
2645  for (int j = 0; j < releases.size (); j++)
2646    {
2647      int new_v = -1;
2648      int new_r = -1;
2649      int new_p = -1;
2650      CmtSystem::is_version_directory (releases[j], new_v, new_r, new_p);
2651      if (v == -1)
2652        {
2653          if (selected_v < new_v)
2654            {
2655              selected_v = new_v;
2656              selected_r = -1;
2657              selected_p = -1;
2658              selected_release = releases[j];
2659            }
2660          else if (selected_v == new_v)
2661            {
2662              // We compare the r
2663              if (selected_r < new_r)
2664                {
2665                  selected_r = new_r;
2666                  selected_p = -1;
2667                  selected_release = releases[j];                               
2668                }
2669              else if (selected_r == new_r)
2670                {
2671                  // We compare the p
2672                  if (selected_p < new_p)
2673                    {
2674                      selected_p = new_p;
2675                      selected_release = releases[j];                               
2676                    }
2677                  // else if ? not possible                                                           
2678                }                               
2679            }
2680        }
2681      else if (r == -1)
2682        {
2683          if (v == new_v)
2684            {
2685              // We compare the r                                                     
2686              if (selected_r < new_r)
2687                {
2688                  selected_r = new_r;
2689                  selected_p = -1;
2690                  selected_release = releases[j];                               
2691                }
2692              else if (selected_r == new_r)
2693                { 
2694                  // We compare the p
2695                  if (selected_p < new_p)
2696                    {
2697                      selected_p = new_p;
2698                      selected_release = releases[j];                               
2699                    }
2700                  // else if ? not possible
2701                }
2702            }
2703        }
2704      else if (p == -1)
2705        {
2706          if ((v == new_v) && (r == new_r))
2707            { 
2708              // We compare the p
2709              if (selected_p < new_p)
2710                {
2711                  selected_p = new_p;
2712                  selected_release = releases[j];                               
2713                }
2714              // else if ? not possible
2715            }       
2716        }       
2717
2718      //cerr << "v:" << new_v << ", r:" << new_r << ", p:" << new_p << endl;             
2719      //cerr << "req v:" << v << ", req r:" << r << ", req p:" << p << endl;       
2720
2721    }
2722
2723  // cerr << "selected release: " << selected_release << endl; 
2724
2725  if (selected_release == "") return false;
2726
2727  result = selected_release;   
2728
2729  return (true);
2730}
2731
2732//---------------------------------------------------------
2733const CmtSystem::cmt_string_vector Project::get_project_releases (const cmt_string& name) const
2734{
2735  CmtSystem::cmt_string_vector releases;
2736  cmt_string cmtprojectpath = Symbol::get_env_value ("CMTPROJECTPATH");
2737
2738  static cmt_string sep = CmtSystem::path_separator ();
2739
2740  CmtSystem::cmt_string_vector items;
2741  CmtSystem::split (cmtprojectpath, sep, items);   
2742
2743  for (int i = 0; i < items.size (); i++)
2744    {
2745      const cmt_string& item = items[i];
2746      cmt_string p = item;
2747      p += CmtSystem::file_separator ();
2748      p += name;
2749
2750      if (CmtSystem::test_directory (p))
2751        { 
2752          CmtSystem::cmt_string_vector directories;
2753          CmtSystem::scan_dir (p, directories);
2754
2755          for (int j = 0; j < directories.size (); j++)
2756            {
2757              if  (CmtSystem::test_directory(directories[j]))
2758                {
2759                  cmt_string release;
2760                  CmtSystem:: basename(directories[j], release);
2761
2762                  if (CmtSystem::is_version_directory(release))
2763                    {                             
2764                      cmt_string& name_entry = releases.add ();
2765                      name_entry = release; 
2766                    }             
2767                }                           
2768            }                           
2769        }
2770    }
2771  return (releases);
2772}
2773
2774//----------------------------------------------------------
2775Project& Project::operator = (const Project& other)
2776{
2777  m_name = other.m_name;
2778  m_cmtpath = other.m_cmtpath;
2779  m_cmtpath_real = other.m_cmtpath_real;
2780  m_cmtpath_pwd = other.m_cmtpath_pwd;
2781  m_cmtpath_source = other.m_cmtpath_source;
2782
2783  return (*this);
2784}
2785
2786//----------------------------------------------------------
2787bool Project::operator == (const cmt_string& name) const
2788{
2789  return ((m_name == name));
2790}
2791
2792//----------------------------------------------------------
2793bool Project::operator != (const cmt_string& name) const
2794{
2795  return ((m_name != name));
2796}
2797
2798//----------------------------------------------------------
2799void Project::show (PrintMode mode)
2800//void Project::show ()
2801{
2802  if (m_visited) return;
2803  m_visited = true;
2804
2805  static int level = 0;
2806
2807  //  bool is_current = false;
2808
2809  //  cmt_string here = CmtSystem::pwd ();
2810  // In case there are symlinks
2811  /*
2812  cmt_string here_real;
2813  CmtSystem::realpath_ (CmtSystem::pwd (), here_real);
2814
2815  //  if (here.find (m_cmtpath) == 0)
2816  if (here_real.find (m_cmtpath_real) == 0)
2817    {
2818      if (m_cmtpath_source != "default path")
2819        {
2820          is_current = true;
2821        }
2822    }
2823  */
2824  switch (mode)
2825    {
2826    case Xml :
2827      cout << "<project" << (m_is_current ? " current=\"yes\"" : "") << ">";
2828      //      if (m_order >= 0)
2829      cout << "<order>" << m_order << "</order>";
2830      cout << "<name>" << m_name << "</name><version>" << (m_name != "CMTUSERCONTEXT" && m_name != "CMTHOME" ? m_release : "v0") << "</version><cmtpath>" << m_cmtpath << "</cmtpath>";
2831      break;
2832    default :
2833  for (int tab = 0; tab < level; tab++) cout << "  ";
2834  cout << m_name << " " << (m_name != "CMTUSERCONTEXT" && m_name != "CMTHOME" ? m_release : "v0") << " (in " << m_cmtpath << ")";
2835  //  cout << m_name << " " << m_release << " (in " << m_cmtpath << ")";
2836
2837  if (m_is_current) cout << " (current)";
2838  //  if (is_current) cout << " (current)";
2839      break;
2840    }
2841
2842  int i;
2843
2844  switch (mode)
2845    {
2846    case Xml :
2847      cout << "<clients>";
2848      break;
2849    }
2850  for (i = 0; i < m_parents.size (); i++)
2851    {
2852      Project* p = m_parents[i];
2853      if (p == 0) continue;
2854      switch (mode)
2855        {
2856        case Xml :
2857          //      cout << "<name>" << p->get_name () << "</name>";
2858          cout << "<project" << (p->is_current () ? " current=\"yes\"" : "") << ">";
2859          //  if (p->m_order >= 0)
2860          cout << "<order>" << p->m_order << "</order>";
2861          cout << "<name>" << p->get_name () << "</name><version>" << (p->get_name () != "CMTUSERCONTEXT" && p->get_name () != "CMTHOME" ? p->get_release () : "v0") << "</version><cmtpath>" << p->get_cmtpath () << "</cmtpath>";
2862          cout << "</project>";
2863          break;
2864        default :
2865      cout << " P=" << p->get_name ();
2866          break;
2867        }
2868    }
2869  switch (mode)
2870    {
2871    case Xml :
2872      cout << "</clients>";
2873      break;
2874    }
2875
2876  switch (mode)
2877    {
2878    case Xml :
2879      cout << "<uses>";
2880      break;
2881    }
2882  for (i = 0; i < m_children.size (); i++)
2883    {
2884      Project* p = m_children[i];
2885      if (p == 0) continue;
2886      switch (mode)
2887        {
2888        case Xml :
2889          //      cout << "<name>" << p->get_name () << "</name>";
2890          cout << "<project" << (p->is_current () ? " current=\"yes\"" : "") << ">";
2891          //      if (p->m_order >= 0)
2892          cout << "<order>" << p->m_order << "</order>";
2893          cout << "<name>" << p->get_name () << "</name><version>" << (p->get_name () != "CMTUSERCONTEXT" && p->get_name () != "CMTHOME" ? p->get_release () : "v0") << "</version><cmtpath>" << p->get_cmtpath () << "</cmtpath>";
2894          cout << "</project>";
2895          break;
2896        default :
2897      cout << " C=" << p->get_name ();
2898          break;
2899        }
2900    }
2901  switch (mode)
2902    {
2903    case Xml :
2904      cout << "</uses>";
2905      cout << "</project>";
2906      break;
2907    default :
2908  cout << endl;
2909      break;
2910    }
2911
2912
2913/*
2914  if (m_visited) return;
2915
2916  m_visited = true;
2917*/
2918
2919  for (i = 0; i < m_children.size (); i++)
2920    {
2921      Project* p = m_children[i];
2922      if (p == 0) continue;
2923      level++;
2924      p->show (mode);
2925      //      p->show ();
2926      level--;
2927    }
2928}
2929
2930
2931//----------------------------------------------------------
2932void Project::show_specified_strategies () const
2933{
2934  int i;
2935
2936  for (i = 0; i < m_strategies.size (); i++)
2937    {
2938      const Strategy& s = m_strategies[i];
2939      if (s.m_specified)
2940        {
2941          const StrategyDef* def = s.m_definition;
2942 
2943          cout << "# Project " << m_name
2944               << " sets " << def->m_keyword
2945               << " strategy to " << ((s.m_value) ? def->m_on_value : def->m_off_value);
2946
2947          if (s.m_context != "")
2948            {
2949              cout << " (from package " << s.m_context << ")";
2950            }
2951
2952          cout << endl;
2953        }
2954    }
2955}
2956
2957//----------------------------------------------------------
2958bool Project::has_strategy (const StrategyDef* definition) const
2959{
2960  int i;
2961
2962  for (i = 0; i < m_strategies.size (); i++)
2963    {
2964      const Strategy& s = m_strategies[i];
2965      if (s.m_definition == definition)
2966        {
2967          return (true);
2968        }
2969    }
2970
2971  return (false);
2972}
2973
2974//----------------------------------------------------------
2975bool Project::get_strategy (const cmt_string& name) const
2976{
2977  static StrategyMgr& mgr = StrategyMgr::instance ();
2978
2979  StrategyDef* def = mgr.find_strategy (name);
2980  if (def == 0)
2981    {
2982      CmtMessage::warning ("strategy " + name + " undefined");
2983      //      cerr << "#CMT> strategy " << name << " undefined" << endl;
2984      return (false);
2985    }
2986
2987  return (get_strategy (def));
2988}
2989
2990//----------------------------------------------------------
2991bool Project::is_specified (const StrategyDef* definition) const
2992{
2993  int i;
2994
2995  for (i = 0; i < m_strategies.size (); i++)
2996    {
2997      Strategy& s = m_strategies[i];
2998      if (s.m_definition == definition)
2999        {
3000          // This strategy is applied in this project
3001          return (s.m_specified);
3002        }
3003    }
3004
3005  // This strategy is not applied in this project
3006  return (false);
3007}
3008
3009//----------------------------------------------------------
3010bool Project::get_strategy (const StrategyDef* def) const
3011{
3012  int i;
3013
3014  for (i = 0; i < m_strategies.size (); i++)
3015    {
3016      Strategy& s = m_strategies[i];
3017      if (s.m_definition == def)
3018        {
3019          // This strategy is applied in this project
3020          if (s.m_specified)
3021            {
3022              return (s.m_specified_value);
3023            }
3024          return (s.m_value);
3025        }
3026    }
3027
3028  // This strategy is not applied in this project
3029  return (def->m_default_value);
3030}
3031
3032//----------------------------------------------------------
3033void Project::set_default_strategy (const cmt_string& name)
3034{
3035  static StrategyMgr& mgr = StrategyMgr::instance ();
3036
3037  StrategyDef* def = mgr.find_strategy (name);
3038  if (def == 0)
3039    {
3040      CmtMessage::warning ("strategy " + name + " undefined");
3041      //      cerr << "#CMT> strategy " << name << " undefined" << endl;
3042      return;
3043    }
3044
3045  update_strategy (def, def->m_default_value);
3046}
3047
3048
3049//----------------------------------------------------------
3050void Project::set_strategy (const cmt_string& name, const cmt_string& value, const cmt_string& context)
3051{
3052  static StrategyMgr& mgr = StrategyMgr::instance ();
3053
3054  StrategyDef* def = mgr.find_strategy (name);
3055  if (def == 0)
3056    {
3057      CmtMessage::warning ("strategy " + name + " undefined");
3058      //      cerr << "#CMT> strategy " << name << " undefined" << endl;
3059      return;
3060    }
3061
3062  bool b_value = false;
3063
3064  if (value == def->m_on_value)
3065    {
3066      b_value = true;
3067    }
3068  else if (value == def->m_off_value)
3069    {
3070      b_value = false;
3071    }
3072  else
3073    {
3074      CmtMessage::warning ("requested strategy value " + value + " undefined in strategy " + name);
3075      //      cerr << "#CMT> requested strategy value " << value << " undefined in strategy " << name << endl;
3076      return;
3077    }
3078
3079  set_strategy (def, b_value, context);
3080}
3081
3082//----------------------------------------------------------
3083void Project::set_strategy (StrategyDef* definition, bool b_value, const cmt_string& context)
3084{
3085  bool need_strategy = true;
3086
3087  int i;
3088
3089  for (i = 0; i < m_strategies.size (); i++)
3090    {
3091      Strategy& s = m_strategies[i];
3092      if (s.m_definition == definition)
3093        {
3094          // This strategy is already applied in this project. Let's change it's value
3095          s.set (definition, b_value, get_name ());
3096          if (context != "")
3097            {
3098              if (s.m_context != "") s.m_context += " ";
3099              s.m_context += context;
3100            }
3101          need_strategy = false;
3102          break;
3103        }
3104    }
3105
3106  if (need_strategy)
3107    {
3108      // This strategy is not yet applied in this project.
3109
3110      Strategy& s = m_strategies.add ();
3111      s.clear ();
3112      s.set (definition, b_value, get_name ());
3113      s.m_context = context;
3114    }
3115 
3116  for (i = 0; i < m_parents.size (); i++)
3117    {
3118      Project* project = m_parents[i];
3119
3120      project->update_strategy (definition, b_value);
3121    }
3122
3123  const ProjectPtrVector& OrderedProjects = Project::ordered_projects ();
3124  for (int i = OrderedProjects.size () - 2; i >= 0; i--)
3125    {
3126      if (this != OrderedProjects[i + 1]) continue;
3127      if (!OrderedProjects[i]->has_parents () &&
3128          OrderedProjects[i]->get_children_size () == 0)
3129        {
3130          OrderedProjects[i]->update_strategy (definition, b_value);
3131        }
3132      break;
3133    }
3134}
3135
3136/**----------------------------------------------------------
3137   The strategy value is changed because of indirect influences
3138   - default strategy at initialization time
3139   - change in the children
3140   - change in the children list
3141
3142   (This is not a specification : see the set_strategy method)
3143*/
3144void Project::update_strategy (StrategyDef* definition, bool b_value)
3145{
3146  bool need_strategy = true;
3147  bool specified = false;
3148
3149  int i;
3150
3151  for (i = 0; i < m_strategies.size (); i++)
3152    {
3153      Strategy& s = m_strategies[i];
3154      if (s.m_definition == definition)
3155        {
3156          need_strategy = false;
3157
3158          if (!s.m_specified)
3159            {
3160              // This strategy is already applied in this project. Let's change it's value
3161              s.update (definition, b_value, get_name ());
3162            }
3163          else
3164            {
3165              specified = true;
3166            }
3167          break;
3168        }
3169    }
3170
3171  if (need_strategy)
3172    {
3173      // This strategy is not yet applied in this project.
3174
3175      Strategy& s = m_strategies.add ();
3176      s.clear ();
3177      s.update (definition, b_value, get_name ());
3178    }
3179
3180  if (!specified)
3181    {
3182      for (i = 0; i < m_parents.size (); i++)
3183        {
3184          Project* project = m_parents[i];
3185
3186          project->update_strategy (definition, b_value);
3187        }
3188
3189      const ProjectPtrVector& OrderedProjects = Project::ordered_projects ();
3190      for (int i = OrderedProjects.size () - 2; i >= 0; i--)
3191        {
3192          if (this != OrderedProjects[i + 1]) continue;
3193          if (!OrderedProjects[i]->has_parents () &&
3194              OrderedProjects[i]->get_children_size () == 0)
3195            {
3196              OrderedProjects[i]->update_strategy (definition, b_value);
3197            }
3198          break;
3199        }
3200    }
3201}
3202
3203/**----------------------------------------------------------
3204   At least one of the children has changed this strategy
3205   Or the list of children has changed.
3206   We need to update the strategy value accordingly
3207   This will not change the specified value for this strategy
3208*/
3209void Project::update_strategy_from_children (StrategyDef* definition)
3210{
3211  // If this strategy is specified we don't care what happens from the children
3212
3213  //cerr << "Updating strategy " << definition->m_name << " from children for project " << m_name << endl;
3214
3215  int i;
3216
3217  for (i = 0; i < m_strategies.size (); i++)
3218    {
3219      Strategy& s = m_strategies[i];
3220      if (s.m_definition == definition)
3221        {
3222          // This strategy is applied in this project.
3223
3224          if (s.m_specified)
3225            {
3226              // There will be no impact since the strategy is specified
3227
3228              //cerr << "This strategy is specified in this project" << endl;
3229              return;
3230            }
3231
3232          break;
3233        }
3234    }
3235
3236  // The strategy is not specified locally so we will now figure out
3237  // which strategy has to be considered from the mixture of specifications
3238  // from all children.
3239
3240  // Algorithm:
3241  // - We consider children by pairs
3242  // - a child that specifies its strategy wins over a child that does not
3243  // - when the two children have the same level of priority we consider the priority value
3244
3245  Project* selected = 0;
3246  bool selected_is_specified = false;
3247  bool selected_value = definition->m_default_value;
3248
3249  for (i = 0; i < m_children.size (); i++)
3250    {
3251      Project* p = m_children[i];
3252
3253      //cerr << "Checking strategy for child " << p->get_name () << endl;
3254
3255      bool is_specified = p->is_specified (definition);
3256      bool value = p->get_strategy (definition);
3257
3258      if (selected == 0)
3259        {
3260          selected = p;
3261          selected_is_specified = is_specified;
3262          selected_value = value;
3263          continue;
3264        }
3265
3266      if (is_specified == selected_is_specified)
3267        {
3268          if (selected_value != value)
3269            {
3270              // same level of priority but different values -> we must decide
3271              bool priority_value = definition->m_priority_value;
3272              if (value == priority_value)
3273                {
3274                  selected = p;
3275                  selected_is_specified = is_specified;
3276                  selected_value = value;
3277                }
3278            }
3279        }
3280      else
3281        {
3282          if (is_specified)
3283            {
3284              selected = p;
3285              selected_is_specified = is_specified;
3286              selected_value = value;
3287            }
3288        }
3289    }
3290
3291  update_strategy (definition, selected_value); 
3292}
3293
3294/**----------------------------------------------------------
3295   At least one of the children has changed its strategies
3296   Or the list of children has changed.
3297   We need to update the strategy values accordingly
3298   This will not change the specified values
3299*/
3300void Project::update_strategies_from_children ()
3301{
3302  StrategyDef::StrategyDefs& defs = StrategyMgr::get_definitions ();
3303
3304  //cerr << "Updating strategies from children for project " << m_name << endl;
3305
3306  int i;
3307
3308  for (i = 0; i < defs.size (); i++)
3309    {
3310      StrategyDef* def = defs[i];
3311     
3312      update_strategy_from_children (def);
3313    }
3314
3315  for (i = 0; i < m_parents.size (); i++)
3316    {
3317      Project* p = m_parents[i];
3318      p->update_strategies_from_children ();
3319    }
3320}
3321
3322/**----------------------------------------------------------
3323   The StrategyMgr singleton
3324*/
3325StrategyMgr& StrategyMgr::instance ()
3326{
3327  static StrategyMgr me;
3328  return (me);
3329}
3330
3331/**----------------------------------------------------------
3332   The StrategyMgr constructor
3333   Here are primarily constructed all strategy definitions
3334*/
3335StrategyMgr::StrategyMgr ()
3336{
3337  m_defs.clear ();
3338
3339  StrategyDef* s;
3340
3341  s = new StrategyDef;
3342  s->m_keyword = "build";
3343  s->m_name = "BuildPrototypes";
3344  s->m_on_value = "prototypes";
3345  s->m_off_value = "no_prototypes";
3346  s->m_default_value = true;
3347  s->m_priority_value = false;
3348
3349  m_defs.push_back (s);
3350
3351  s = new StrategyDef;
3352  s->m_keyword = "build";
3353  s->m_name = "InstallArea";
3354  s->m_on_value = "with_installarea";
3355  s->m_off_value = "without_installarea";
3356  s->m_default_value = false;
3357  s->m_priority_value = true;
3358
3359  m_defs.push_back (s);
3360
3361  s = new StrategyDef;
3362  s->m_keyword = "setup";
3363  s->m_name = "SetupConfig";
3364  s->m_on_value = "config";
3365  s->m_off_value = "no_config";
3366  s->m_default_value = true;
3367  s->m_priority_value = false;
3368
3369  m_defs.push_back (s);
3370
3371  s = new StrategyDef;
3372  s->m_keyword = "setup";
3373  s->m_name = "SetupRoot";
3374  s->m_on_value = "root";
3375  s->m_off_value = "no_root";
3376  s->m_default_value = true;
3377  s->m_priority_value = false;
3378
3379  m_defs.push_back (s);
3380
3381  s = new StrategyDef;
3382  s->m_keyword = "setup";
3383  s->m_name = "SetupCleanup";
3384  s->m_on_value = "cleanup";
3385  s->m_off_value = "no_cleanup";
3386  s->m_default_value = true;
3387  s->m_priority_value = false;
3388
3389  m_defs.push_back (s);
3390
3391  s = new StrategyDef;
3392  s->m_keyword = "setup";
3393  s->m_name = "SetupScripts";
3394  s->m_on_value = "scripts";
3395  s->m_off_value = "no_scripts";
3396  s->m_default_value = true;
3397  s->m_priority_value = false;
3398
3399  m_defs.push_back (s);
3400
3401  s = new StrategyDef;
3402  s->m_keyword = "structure";
3403  s->m_name = "VersionDirectory";
3404  s->m_on_value = "with_version_directory";
3405  s->m_off_value = "without_version_directory";
3406  if (Cmt::get_current_structuring_style () != without_version_directory)
3407    {
3408      s->m_default_value = true;
3409      s->m_priority_value = false;
3410    }
3411  else
3412    {
3413      s->m_default_value = false;
3414      s->m_priority_value = true;
3415    }
3416
3417  m_defs.push_back (s);
3418}
3419
3420/**----------------------------------------------------------
3421   Find a strategy definition by its name
3422*/
3423StrategyDef* StrategyMgr::find_strategy (const cmt_string& name)
3424{
3425  static StrategyMgr& me = instance ();
3426
3427  int i;
3428
3429  for (i = 0; i < me.m_defs.size (); i++)
3430    {
3431      StrategyDef* def = me.m_defs[i];
3432      if (def->m_name == name)
3433        {
3434          return (def);
3435        }
3436    }
3437
3438  return (0);
3439}
3440
3441/**----------------------------------------------------------
3442   Retreive the default value defined for a given strategy
3443*/
3444bool StrategyMgr::get_default_strategy (const cmt_string& name)
3445{
3446  StrategyDef* def = find_strategy (name);
3447  if (def == 0) return (false);
3448  return (def->m_default_value);
3449}
3450
3451/**----------------------------------------------------------
3452   Retreive the priority value defined for a given strategy
3453   This value is used when two children of a project request two conflicting strategy values
3454*/
3455bool StrategyMgr::get_priority_strategy (const cmt_string& name)
3456{
3457  StrategyDef* def = find_strategy (name);
3458  if (def == 0) return (false);
3459  return (def->m_priority_value);
3460}
3461
3462/**----------------------------------------------------------
3463   Return the vector of all existing strategy definitions
3464*/
3465StrategyDef::StrategyDefs& StrategyMgr::get_definitions ()
3466{
3467  static StrategyMgr& me = instance ();
3468
3469  return (me.m_defs);
3470}
3471
3472//-----------------------------------------------------------
3473Strategy::Strategy ()
3474{
3475  clear ();
3476}
3477
3478//-----------------------------------------------------------
3479void Strategy::clear ()
3480{
3481  m_definition = 0;
3482  m_specified = false;
3483  m_specified_value = false;
3484  m_value = false;
3485  m_on_tag = 0;
3486  m_off_tag = 0;
3487}
3488
3489/**----------------------------------------------------------
3490   Specify a new value for this strategy.
3491   This only happens when a strategy statement is met in a project file or in a requirements file.
3492*/
3493void Strategy::set (StrategyDef* definition, bool value, const cmt_string& project_name)
3494{
3495  //cerr << "Setting strategy " << definition->m_name << " for project " << project_name << " to " << value << endl;
3496
3497  m_definition = definition;
3498  m_specified = true;
3499  m_specified_value = value;
3500
3501  update (definition, value, project_name);
3502}
3503
3504/**----------------------------------------------------------
3505   Change the effective value for this strategy.
3506   This has no impact on to the specified value.
3507   This will adapt the tag settings
3508*/
3509void Strategy::update (StrategyDef* definition, bool value, const cmt_string& project_name)
3510{
3511  //cerr << "Updating strategy " << definition->m_name << " for project " << project_name << " to " << value << endl;
3512
3513  m_value = value;
3514  m_definition = definition;
3515
3516  cmt_string to_tag_name = project_name;
3517  cmt_string to_untag_name = project_name;
3518
3519  to_tag_name += "_";
3520  to_untag_name += "_";
3521
3522  if (m_value)
3523    {
3524      to_tag_name += m_definition->m_on_value;
3525      to_untag_name += m_definition->m_off_value;
3526    }
3527  else
3528    {
3529      to_tag_name += m_definition->m_off_value;
3530      to_untag_name += m_definition->m_on_value;
3531    }
3532
3533  m_on_tag = Tag::find (to_tag_name);
3534  m_off_tag = Tag::find (to_untag_name);
3535
3536  if (m_on_tag == 0 || m_off_tag == 0)
3537    {
3538      m_on_tag = Tag::add (to_tag_name, PriorityConfig, "PROJECT", 0);
3539      m_off_tag = Tag::add (to_untag_name, PriorityConfig, "PROJECT", 0);
3540
3541      m_on_tag->add_tag_exclude (m_off_tag);
3542      m_off_tag->add_tag_exclude (m_on_tag);
3543    }
3544
3545  m_off_tag->unmark ();
3546  m_on_tag->mark ("PROJECT");
3547}
3548
3549//-----------------------------------------------------------
3550const cmt_string& StrategyDef::get_default_value () const
3551{
3552  if (m_default_value)
3553    {
3554      return (m_on_value);
3555    }
3556  else
3557    {
3558      return (m_off_value);
3559    }
3560}
3561
3562//-----------------------------------------------------------
3563void Project::set_author (const cmt_string& name)
3564{
3565  // cerr << "set_author" << name << endl;     
3566  this->m_author = name;
3567}
3568
3569//-----------------------------------------------------------
3570const cmt_string& Project::get_author () const
3571{
3572  return (m_author);
3573}
3574
3575//-----------------------------------------------------------
3576void Project::project_author_action (const CmtSystem::cmt_string_vector& words)
3577{
3578  if (m_author != "") m_author += "\n";
3579
3580  for (int i = 1; i < words.size (); i++)
3581    {
3582      const cmt_string& w = words[i];
3583     
3584      if (i > 1) m_author += " ";
3585      m_author += w; 
3586    }
3587}
3588
3589//-----------------------------------------------------------
3590Use*  Project::get_use () const
3591{
3592  return m_use;   
3593} 
3594
3595//-----------------------------------------------------------
3596void  Project::set_use (Use* use)
3597{ 
3598  this->m_use = use;
3599}
3600
3601//-----------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.