Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

cmt_project.cxx

Go to the documentation of this file.
00001 //-----------------------------------------------------------
00002 // Copyright Christian Arnault LAL-Orsay CNRS
00003 // arnault@lal.in2p3.fr
00004 // See the complete license in cmt_license.txt "http://www.cecill.info". 
00005 //-----------------------------------------------------------
00006 
00007 #include <stdio.h>
00008 #include <stdlib.h>
00009 #include <string.h>
00010 #include <ctype.h>
00011 
00012 #include "cmt_project.h"
00013 #include "cmt_database.h"
00014 #include "cmt_system.h"
00015 #include "cmt_awk.h"
00016 #include "cmt_syntax.h"
00017 #include "cmt_tag.h"
00018 #include "cmt_error.h"
00019 
00020 class ProjectReader : public Awk
00021 {
00022 public:
00023 
00024   ProjectReader ()
00025   {
00026   }
00027   
00028   const cmt_string& get_project_name () const
00029   {
00030     return (m_project);
00031   }
00032   
00033   void filter (const cmt_string& line)
00034   {
00035     CmtSystem::cmt_string_vector words;
00036     CmtSystem::split (line, " \t", words);
00037     if (words[0] == "project")
00038       {
00039         m_project = words[1];
00040       }
00041   }
00042   
00043 private:
00044   cmt_string m_project;
00045 };
00046 
00047 class ProjectPatcher : public Awk
00048 {
00049 public:
00050 
00051   ProjectPatcher (const cmt_string& p) : m_project (p)
00052   {
00053   }
00054 
00055   void commit ()
00056   {
00057     m_output.write (Project::get_project_file_name ());
00058   }
00059 
00060   void filter (const cmt_string& line)
00061   {
00062     if (m_output != "")
00063       {
00064         m_output += "\n";
00065       }
00066     
00067     CmtSystem::cmt_string_vector words;
00068     CmtSystem::split (line, " \t", words);
00069     if (words[0] == "project")
00070       {
00071         m_output += "project ";
00072         m_output += m_project;
00073       }
00074     else
00075       {
00076         m_output += line;
00077       }
00078   }
00079   
00080 private:
00081   cmt_string m_output;
00082   const cmt_string& m_project;
00083 };
00084 
00085 IProjectFactory& ProjectFactory::instance ()
00086 {
00087   static ProjectFactory me;
00088   
00089   return (me);
00090 }
00091 
00092 void ProjectFactory::reset ()
00093 {
00094   Project::clear_all ();
00095 }
00096 
00097 static bool get_release_from_path (const CmtSystem::cmt_string_vector& items, 
00098                                    const cmt_string& path, 
00099                                    const cmt_string& name, 
00100                                    cmt_string& real_name, 
00101                                    cmt_string& release)
00102 {
00103   bool result = false;
00104 
00105   release = "";
00106   real_name = "";
00107 
00108   cmt_string p = path;
00109 
00110   if ((items.size () == 0) && (name == ""))
00111     {
00112       // There is no CMTPROJECTPATH and no expected project name.
00113       // We have no way to find a project structure
00114       // So we only expect a 2-level structure.
00115 
00116       CmtSystem::basename (p, release);
00117       CmtSystem::dirname (p, p);
00118       CmtSystem::basename (p, real_name);
00119       
00120       return (false);
00121     }
00122 
00123   for (;;)
00124     {
00125       if (p == "")
00126         {
00127           // Protection: we found no matching project name
00128           // and path was outside any CMTPROJECTPATH
00129 
00130           p = path;
00131 
00132           CmtSystem::basename (p, release);
00133           CmtSystem::dirname (p, p);
00134           CmtSystem::basename (p, real_name);
00135 
00136           return (false);
00137         }
00138 
00139       cmt_string n;
00140 
00141       CmtSystem::basename (p, n);
00142       CmtSystem::dirname (p, p);
00143 
00144       if (n == name)
00145         {
00146           real_name = name;
00147           result = true;
00148           break;
00149         }
00150 
00151       CmtSystem::basename (p, real_name);
00152 
00153       for (int i = 0; i < items.size (); i++)
00154         {
00155           const cmt_string& item = items[i];
00156           if (p == item)
00157             {
00158               // We have reached an item of CMTPROJECTPATH, no need to continue
00159               return (false);
00160             }
00161         }
00162 
00163       if (release == "")
00164         {
00165           release = n;
00166         }
00167       else
00168         {
00169           cmt_string r;
00170 
00171           r = n;
00172           r += CmtSystem::file_separator ();
00173           r += release;
00174           release = r;
00175         }
00176     }
00177 
00178   //cerr << "$CMT> GRFP> path=" << path << " name=" << name << " rel=" << release << endl;
00179 
00180   return (result);
00181 }
00182  
00183 
00184 /*
00185   Every new CMTPATH entry becomes associated with a dedicated PROJECT
00186   This function will understand this new entry to CMTPATH and understand it:
00187   - it can correspond to an existing project (ie already declared)
00188   - it's a new project
00189      - then it tries to read and parse its project file 
00190  */
00191 Project* ProjectFactory::create_project (const cmt_string& specified_name,
00192                                          const cmt_string& path,
00193                                          const cmt_string& source,
00194                                          Project* parent)
00195 {
00196   cmt_string compressed_path = path;
00197   CmtSystem::compress_path (compressed_path);
00198   bool specify_name = (specified_name != "");
00199 
00200   if (Cmt::get_debug ())
00201     {
00202       cout << "Creating project " << path << " with parent " << ((parent==0)? "0" : parent->get_name ()) << endl;
00203       Project::show_all ();
00204     }
00205 
00206   cmt_string sep;
00207   sep = CmtSystem::path_separator ();
00208 
00209   cmt_string cmtprojectpath = CmtSystem::getenv ("CMTPROJECTPATH");
00210   CmtSystem::cmt_string_vector items;
00211   CmtSystem::split (cmtprojectpath, sep, items);
00212 
00213   cmt_string here = CmtSystem::pwd ();
00214   if (!CmtSystem::cd (compressed_path)) return (0);
00215   cmt_string pwd = CmtSystem::pwd ();
00216 
00217   static Project::ProjectVector& Projects = Project::projects ();
00218   
00219   for (int i = 0; i < Projects.size (); i++)
00220     {
00221       Project& p = Projects[i];
00222       
00223       if ((p.get_cmtpath () == compressed_path) ||
00224           (p.get_cmtpath_pwd () == pwd) ||
00225           (specify_name && (p.get_name () == specified_name)))
00226         {
00227           cmt_string r;
00228           cmt_string n;
00229 
00230           get_release_from_path (items, compressed_path, p.get_name (), n, r);
00231 
00232           if (r != p.get_release ())
00233             {
00234               cerr << "#CMT> Project " << p.get_name ()
00235                    << " requested with conflicting releases " << p.get_release () << " and " << r << endl;
00236               CmtError::set (CmtError::project_release_conflict, p.get_name ());
00237             }
00238   
00239           if (parent != 0)
00240             {
00241               p.add_parent (parent);
00242               parent->add_child (&p);
00243 
00244               // Since p is a new parent, we should propagate the settings UP.
00245 
00246               parent->update_strategies_from_children ();
00247             }
00248 
00249           CmtSystem::cd (here);
00250           return (&p);
00251         }
00252     }
00253 
00254 
00255   Project* project = 0;
00256   Project* cmt = 0;
00257   
00258   bool is_current = false;
00259   
00260   cmt_string name = specified_name;
00261   cmt_string project_name;
00262   cmt_string release;
00263 
00264   //
00265   // Figure out if this is the current project
00266   //
00267   if (here.find (pwd) == 0) is_current = true;
00268 
00269   cmt_string text;
00270 
00271   /*
00272     Now Figure out the project name from the project file
00273        or does not specify the project name
00274    */
00275   bool has_project_file = false;
00276 
00277   if (CmtSystem::cd ("cmt") && CmtSystem::test_file (Project::get_project_file_name ()))
00278     {
00279       has_project_file = true;
00280       text.read (Project::get_project_file_name ());
00281 
00282       ProjectReader reader;
00283 
00284       reader.run (text);
00285 
00286       project_name = reader.get_project_name ();
00287     }
00288 
00289   enum
00290     {
00291       without_project_file   = 0x01,
00292       with_project_file      = 0x02,
00293       without_project_name   = 0x04,
00294       with_project_name      = 0x08,
00295       without_specified_name = 0x10,
00296       with_specified_name    = 0x20,
00297       names_mismatch         = 0x40,
00298       names_match            = 0x80
00299     };
00300 
00301   int status = ((has_project_file) ? with_project_file : without_project_file) |
00302     ((has_project_file && (project_name != "")) ? with_project_name : without_project_name) |
00303     ((specify_name) ? with_specified_name : without_specified_name) |
00304     ((specify_name && has_project_file && (project_name == specified_name)) ? names_match : names_mismatch);
00305 
00306   if (source == "default path")
00307     {
00308       name = "CMT";
00309     }
00310   else
00311     {
00312       cmt_string n;
00313           
00314       switch (status)
00315         {
00316         case with_project_file | without_project_name | without_specified_name | names_mismatch:
00317 
00318           // The project is neither specified from the caller nor from the project file
00319 
00320           /*
00321             if (!Cmt::get_quiet ())
00322             {
00323             cerr << "#CMT> Warning: project name unspecified in project file." << endl;
00324             }
00325           */
00326       
00327           get_release_from_path (items, compressed_path, "", name, release);
00328 
00329           break;
00330           
00331         case with_project_file | without_project_name | with_specified_name | names_mismatch:
00332           
00333           // The name is only specified from the caller
00334           // find this specified name in the path
00335           
00336           if (get_release_from_path (items, compressed_path, specified_name, name, release))
00337             {
00338               // The specified name has been found from the path.
00339               // We believe in the release spec.
00340             }
00341           else
00342             {
00343               // The specified name is not in the path.
00344               /*
00345               if (!Cmt::get_quiet ())
00346                 {
00347                   cerr << "#CMT> Warning: specified project name "
00348                        << specified_name
00349                        << " from the caller does not match path." << endl;
00350                 }
00351               */
00352               name = specified_name;
00353             }
00354           
00355           break;
00356           
00357         case with_project_file | with_project_name | with_specified_name | names_match:
00358           
00359           // We have a double specification: from the caller and from the project file.
00360           // And both specifications are consistent.  
00361           
00362           if (get_release_from_path (items, compressed_path, specified_name, name, release))
00363             {
00364               // The specified name has been found from the path.
00365               // We believe in the release spec.
00366             }
00367           else
00368             {
00369               // The specified name is not in the path.
00370               /*
00371               if (!Cmt::get_quiet ())
00372                 {
00373                   cerr << "#CMT> Warning: specified project name "
00374                        << specified_name
00375                        << " from project file and from caller does not match path." << endl;
00376                 }
00377               */
00378               name = specified_name;
00379             }
00380           
00381           break;
00382           
00383         case with_project_file | with_project_name | with_specified_name | names_mismatch:
00384           
00385           // We have a double specification: from the caller and from the project file.
00386           // Specifications are inconsistent!!
00387           
00388           if (!Cmt::get_quiet ())
00389             {
00390               cerr << "#CMT> Warning: specified project name "
00391                    << specified_name
00392                    << " inconsistent with name "
00393                    << project_name
00394                    << " from project file." << endl;
00395             }
00396           
00397           if (get_release_from_path (items, compressed_path, specified_name, n, release))
00398             {
00399               // name from caller wins.
00400             }
00401           else if (get_release_from_path (items, compressed_path, project_name, name, release))
00402             {
00403               // name from project file wins.
00404             }
00405           else
00406             {
00407               // The specified name is not in the path.
00408               
00409               if (!Cmt::get_quiet ())
00410                 {
00411                   cerr << "#CMT> Warning: none of specified project names "
00412                        << specified_name
00413                        << " from graph and "
00414                        << project_name
00415                        << " from project file match path." << endl;
00416                 }
00417 
00418               name = specified_name;
00419             }
00420           
00421           break;
00422           
00423         case with_project_file | with_project_name | without_specified_name | names_mismatch:
00424           
00425           // Project name is specified in the project file but not from the caller.
00426           
00427           if (get_release_from_path (items, compressed_path, project_name, name, release))
00428             {
00429               // The specified name has been found from the path.
00430               // We believe in the release spec.
00431 
00432             }
00433           else
00434             {
00435               // The specified name is not in the path.
00436 
00437               /*
00438               if (!Cmt::get_quiet ())
00439                 {
00440                   cerr << "#CMT> Warning: specified project name "
00441                        << project_name
00442                        << " from project file does not match path." << endl;
00443                 }
00444               */
00445 
00446               name = project_name;
00447             }
00448           
00449           break;
00450           
00451         case without_project_file | without_project_name | without_specified_name | names_mismatch:
00452           
00453           // The project is not specified from the caller and there is no project file
00454           // This corresponds to the backward compatibility
00455           // For the moment, assume /name/release/ structure where release is one level only
00456           
00457           /*
00458             if (!Cmt::get_quiet ())
00459             {
00460             cerr << "#CMT> Warning: project name is not specified "
00461             << " (no project file)." << endl;
00462             }
00463           */
00464           
00465           CmtSystem::basename (compressed_path, release);
00466           CmtSystem::dirname (compressed_path, name);
00467           CmtSystem::basename (name, name);
00468           
00469           break;
00470           
00471         case without_project_file | without_project_name | with_specified_name | names_mismatch:
00472           
00473           // The name is only specified from the caller
00474           // find this specified name in the path
00475           
00476           if (get_release_from_path (items, compressed_path, specified_name, name, release))
00477             {
00478               // The specified name has been found from the path.
00479               // We believe in the release spec.
00480             }
00481           else
00482             {
00483               // The specified name is not in the path.
00484               /*
00485               if (!Cmt::get_quiet ())
00486                 {
00487                   cerr << "#CMT> Warning: specified project name "
00488                        << specified_name
00489                        << " from project graph does not match path." << endl;
00490                 }
00491               */
00492               name = specified_name;
00493             }
00494           
00495           break;
00496         }
00497     }
00498 
00499   project = Project::add (name, release);
00500       
00501   if (parent != 0)
00502     {
00503       project->add_parent (parent);
00504       parent->add_child (project);
00505 
00506       // Since p is a new parent, we should propagate the settings UP.
00507 
00508       parent->update_strategies_from_children ();
00509     }
00510 
00511   if (source == "default path")
00512     {
00513       cmt = project;
00514       is_current = false;
00515     }
00516 
00517   project->set_cmtpath (compressed_path);
00518   project->set_cmtpath_pwd (pwd);
00519   project->set_cmtpath_source (source);
00520 
00521   if (is_current)
00522     {
00523       //
00524       // The current project defines a tag with its name
00525       //
00526 
00527       Tag* tag;
00528       
00529       tag = Tag::add (project->get_name (), PriorityConfig, "PROJECT", 0);
00530       tag->mark ();
00531     }
00532 
00533   if (text != "")
00534     {
00535       // Last step is to parse the project file
00536 
00537       SyntaxParser::parse_project_file_text (text, 
00538                                              Project::get_project_file_name (),
00539                                              project);
00540     }
00541 
00542   CmtSystem::cd (here);
00543 
00544   return (project);
00545 }
00546 
00547 /*----------------------------------------------------------*/
00548 /*                                                          */
00549 /*  Operations on Projects                                  */
00550 /*                                                          */
00551 /*----------------------------------------------------------*/
00552 
00553 //----------------------------------------------------------
00554 void Project::create (const cmt_string& name, 
00555                       const cmt_string& release, 
00556                       const cmt_string& path)
00557 {
00558   cout << "------------------------------------------" << endl;
00559   cout << "Configuring environment for project " << name << " " << release;
00560 
00561   if (path != "")
00562     {
00563       cout << " in " << path;
00564     }
00565 
00566   cout << endl;
00567   cout << "CMT version " << Cmt::get_cmt_version () << "." << endl;
00568   cout << "------------------------------------------" << endl;
00569 
00570   if (path != "")
00571     {
00572       if (!CmtSystem::mkdir (path))
00573         {
00574           cout << "Cannot create the " << path << " directory" << endl;
00575           return;
00576         }
00577 
00578       if (!CmtSystem::cd (path))
00579         {
00580           cout << "Cannot access the " << path << " directory" << endl;
00581           return;
00582         }
00583     }
00584 
00585   if (!CmtSystem::mkdir (name))
00586     {
00587       cout << "Cannot create the " << name << " directory" << endl;
00588       return;
00589     }
00590 
00591   if (!CmtSystem::cd (name))
00592     {
00593       cout << "Cannot access the " << name << " directory" << endl;
00594       return;
00595     }
00596 
00597   if (release != "")
00598     {
00599       if (!CmtSystem::mkdir (release))
00600         {
00601           cout << "Cannot create the " << release << " directory" << endl;
00602           return;
00603         }
00604       
00605       if (!CmtSystem::cd (release))
00606         {
00607           cout << "Cannot access the " << release << " directory" << endl;
00608           return;
00609         }
00610     }
00611 
00612   if (!CmtSystem::test_directory ("cmt"))
00613     {
00614       if (!CmtSystem::mkdir ("cmt"))
00615         {
00616           cout << "Cannot create the cmt directory" << endl;
00617           return;
00618         }
00619       else
00620         {
00621           cout << "Installing the cmt directory" << endl;
00622         }
00623     }
00624 
00625   CmtSystem::cd ("cmt");
00626 
00627   if (!CmtSystem::test_file (get_project_file_name ()))
00628     {
00629       cout << "Creating a new project file" << endl;
00630 
00631       ofstream f (get_project_file_name ());
00632       if (f)
00633         {
00634           f << "project " << name << endl;
00635           f << endl;
00636           f.close ();
00637         }
00638     }
00639   else
00640     {
00641       cmt_string text;
00642       text.read (get_project_file_name ());
00643 
00644       ProjectPatcher p (name);
00645 
00646       p.run (text);
00647       p.commit ();
00648 
00649       cout << "project file already there" << endl;
00650     }
00651 }
00652 
00653 //----------------------------------------------------------
00654 Project* Project::find_by_name (const cmt_string& name)
00655 {
00656   static ProjectVector& Projects = projects ();
00657 
00658   for (int i = 0; i < Projects.size (); i++)
00659     {
00660       Project& p = Projects[i];
00661 
00662       if (p.m_name == name) return (&p);
00663     }
00664 
00665   return (0);
00666 }
00667 
00668 //----------------------------------------------------------
00669 Project* Project::find_by_cmtpath (const cmt_string& cmtpath)
00670 {
00671   cmt_string compressed_path = cmtpath;
00672   CmtSystem::compress_path (compressed_path);
00673 
00674   static ProjectVector& Projects = projects ();
00675 
00676   for (int i = 0; i < Projects.size (); i++)
00677     {
00678       Project& p = Projects[i];
00679 
00680       if (p.m_cmtpath == compressed_path) return (&p);
00681       if (p.m_cmtpath_pwd == compressed_path) return (&p);
00682     }
00683 
00684   return (0);
00685 }
00686 
00687 //----------------------------------------------------------
00688 Project* Project::get_current ()
00689 {
00690   cmt_string here = CmtSystem::pwd ();
00691 
00692   static ProjectVector& Projects = projects ();
00693 
00694   Project* result = 0;
00695 
00696   for (int i = (Projects.size () - 1); i >= 0; i--)
00697     {
00698       Project& p = Projects[i];
00699 
00700       if (here.find (p.m_cmtpath_pwd) == 0) 
00701         {
00702           result = &p;
00703         }
00704 
00705       if (here.find (p.m_cmtpath) == 0) 
00706         {
00707           result = &p;
00708         }
00709     }
00710 
00711   return (result);
00712 }
00713 
00714 //----------------------------------------------------------
00715 Project* Project::add (const cmt_string& name,
00716                        const cmt_string& release)
00717 {
00718   static ProjectVector& Projects = projects ();
00719 
00720   //cout << "Project::add> name=" << name << endl;
00721 
00722   {
00723     Project* project;
00724 
00725     project = find_by_name (name);
00726     if (project != 0) 
00727       {
00728         if (!Cmt::get_quiet ())
00729           {
00730             if (release != project->get_release ())
00731               {
00732                 cerr << "#CMT> Project " << name << " requested with conflicting releases " << project->get_release () << " and " << release << endl;
00733                 CmtError::set (CmtError::project_release_conflict, name);
00734               }
00735           }
00736 
00737         // Project objects are recreated here to follow the hierarchy
00738         // This duplication is needed for properly applying the strategies
00739         Project& p = Projects.add ();
00740 
00741         p.set_name (name);
00742         p.set_release (release);
00743         p.configure ();
00744 
00745         return (&p);
00746 
00747         //return (project);
00748       }
00749   }
00750 
00751   Project& project = Projects.add ();
00752   project.clear ();
00753   project.set_name (name);
00754   project.set_release (release);
00755   project.configure ();
00756 
00757   return (&project);
00758 }
00759 
00760 //----------------------------------------------------------
00761 Project::ProjectVector& Project::projects ()
00762 {
00763   static Database& db = Database::instance ();
00764   static ProjectVector& Projects = db.projects ();
00765 
00766   return (Projects);
00767 }
00768 
00769 /*----------------------------------------------------------*/
00770 void Project::clear_all ()
00771 {
00772   static ProjectVector& Projects = projects ();
00773 
00774   for (int i = 0; i < Projects.size (); i++)
00775     {
00776       Project& project = Projects[i];
00777       project.clear ();
00778     }
00779 
00780   Projects.clear ();
00781 }
00782 
00783 /*----------------------------------------------------------*/
00784 void Project::show_all ()
00785 {
00786   static Project::ProjectVector& Projects = Project::projects ();
00787   
00788   for (int i = 0; i < Projects.size (); i++)
00789     {
00790       Project& p = Projects[i];
00791       p.m_visited = false;
00792     }
00793 
00794   Project* current = get_current ();
00795 
00796   if (current != 0) current->show ();
00797 }
00798 
00799 /*----------------------------------------------------------*/
00800 void Project::show_specified_strategies_for_all ()
00801 {
00802   static ProjectVector& Projects = projects ();
00803 
00804   for (int i = 0; i < Projects.size (); i++)
00805     {
00806       const Project& project = Projects[i];
00807       project.show_specified_strategies ();
00808     }
00809 }
00810 
00811 /*----------------------------------------------------------*/
00812 class VisitorForShowPaths : public IProjectVisitor
00813 {
00814 public:
00815   VisitorForShowPaths ()
00816   {
00817   }
00818 
00819   void pre (Project* p)
00820   {
00821     const cmt_string& w = p->get_cmtpath_pwd ();
00822     const cmt_string& s = p->get_cmtpath_source ();
00823 
00824     if (s == "default path") return;
00825 
00826     if (CmtSystem::test_directory (w))
00827       {
00828         cout << "# Add path " << w << " from " << s << endl;
00829       }
00830   }
00831 
00832   void in (Project* p)
00833   {
00834     const cmt_string& w = p->get_cmtpath_pwd ();
00835     const cmt_string& s = p->get_cmtpath_source ();
00836 
00837     if (s == "default path") return;
00838 
00839     if (CmtSystem::test_directory (w))
00840       {
00841         cout << "# Add path " << w << " from " << s << endl;
00842       }
00843   }
00844 
00845   void post (Project* p)
00846   {
00847   }
00848 };
00849 
00850 /*----------------------------------------------------------*/
00851 void Project::show_paths ()
00852 {
00853   VisitorForShowPaths visitor;
00854 
00855   start_visit (visitor);
00856 }
00857 
00858 //----------------------------------------------------------
00859 const cmt_string& Project::get_project_file_name ()
00860 {
00861   static const cmt_string name = "project.cmt";
00862 
00863   return (name);
00864 }
00865 
00866 //----------------------------------------------------------
00867 void Project::fill_selection (int depth, CmtSystem::cmt_string_vector& path_selections)
00868 {
00869   static ProjectVector& Projects = projects ();
00870 
00871   for (int i = 0; i < Projects.size (); i++)
00872     {
00873       Project& project = Projects[i];
00874 
00875       const cmt_string& p = project.get_cmtpath ();
00876       const cmt_string& pwd = project.get_cmtpath_pwd ();
00877       const cmt_string& src = project.get_cmtpath_source ();
00878 
00879       if (src != "default path")
00880         {
00881           if (depth > 0)
00882             {
00883               cmt_string& s1 = path_selections.add ();
00884               s1 = p;
00885               cmt_string& s2 = path_selections.add ();
00886               s2 = pwd;
00887               depth--;
00888 
00889               if (depth == 0) break;
00890             }
00891         }
00892     }
00893 }
00894 
00895 //----------------------------------------------------------
00896 void Project::broadcast (IProjectAction& action)
00897 {
00898   static ProjectVector& Projects = projects ();
00899 
00900   for (int i = 0; i < Projects.size (); i++)
00901     {
00902       const Project& project = Projects[i];
00903 
00904       if (!action.run (project)) break;
00905     }
00906 }
00907 
00908 //----------------------------------------------------------
00909 void Project::reverse_broadcast (IProjectAction& action)
00910 {
00911   static ProjectVector& Projects = projects ();
00912 
00913   for (int i = (Projects.size () - 1); i >= 0; i--)
00914     {
00915       const Project& project = Projects[i];
00916 
00917       if (!action.run (project)) break;
00918     }
00919 }
00920 
00921 //----------------------------------------------------------
00922 void Project::scan_paths (PathScanner& scanner, PathScanner::actor& a)
00923 {
00924   static ProjectVector& Projects = projects ();
00925 
00926   for (int i = 0; i < Projects.size (); i++)
00927     {
00928       const Project& project = Projects[i];
00929 
00930       const cmt_string& p = project.m_cmtpath;
00931       scanner.scan_path (p, a);
00932     }
00933 }
00934 
00935 //----------------------------------------------------------
00936 void Project::scan_paths_for_package (PathScanner& scanner, const cmt_string& name)
00937 {
00938   static ProjectVector& Projects = projects ();
00939 
00940   for (int i = 0; i < Projects.size (); i++)
00941     {
00942       const Project& project = Projects[i];
00943 
00944       const cmt_string& p = project.m_cmtpath;
00945       scanner.scan_package (p, name);
00946     }
00947 }
00948 
00949 //----------------------------------------------------------
00950 cmt_string Project::find_in_cmt_paths (const cmt_string& path)
00951 {
00952   const cmt_string pwd = CmtSystem::pwd ();
00953 
00954   static ProjectVector& Projects = projects ();
00955 
00956   for (int i = 0; i < Projects.size (); i++)
00957     {
00958       const Project& project = Projects[i];
00959 
00960       const cmt_string& p = project.m_cmtpath;
00961       const cmt_string& w = project.m_cmtpath_pwd;
00962       const cmt_string& s = project.m_cmtpath_source;
00963 
00964       if (s == "default path") continue;
00965 
00966       if (CmtSystem::test_directory (p))
00967         {
00968           if (path.find (p) != cmt_string::npos)
00969             {
00970               return (p);
00971             }
00972 
00973           // To become the current area, a path must correspond to the current package
00974           if (path.find (w) != cmt_string::npos)
00975             {
00976               return (p);
00977             }
00978         }
00979 
00980       if (p == w) continue;
00981 
00982       if (CmtSystem::test_directory (w))
00983         {
00984           if (path.find (w) != cmt_string::npos)
00985             {
00986               return (w);
00987             }
00988         }
00989     }
00990 
00991   return ("");
00992 }
00993 
00994 //----------------------------------------------------------
00995 void Project::visit (IProjectVisitor& visitor)
00996 {
00997   if (m_visited) return;
00998   m_visited = true;
00999 
01000   int i;
01001 
01002   for (i = 0; i < get_children_size (); i++)
01003     {
01004       Project* child = get_child (i);
01005 
01006       if (child->visited ()) continue;
01007 
01008       visitor.in (child);
01009     }
01010 
01011   for (i = 0; i < m_children.size (); i++)
01012     {
01013       Project* child = m_children[i];
01014       child->visit (visitor);
01015     }
01016 }
01017 
01018 //----------------------------------------------------------
01019 void Project::start_visit (IProjectVisitor& visitor)
01020 {
01021   static Project::ProjectVector& Projects = Project::projects ();
01022   
01023   for (int i = 0; i < Projects.size (); i++)
01024     {
01025       Project& p = Projects[i];
01026       p.m_visited = false;
01027     }
01028 
01029   Project* p = get_current ();
01030 
01031   if (p == 0) return;
01032 
01033   visitor.pre (p);
01034   p->visit (visitor);
01035   visitor.post (p);
01036 }
01037 
01038 //----------------------------------------------------------
01039 class VisitorForFillCMTPATH : public IProjectVisitor
01040 {
01041 public:
01042   VisitorForFillCMTPATH (cmt_string& buffer) : m_buffer (buffer)
01043   {
01044   }
01045 
01046   void pre (Project* p)
01047   {
01048     const cmt_string& w = p->get_cmtpath_pwd ();
01049     const cmt_string& s = p->get_cmtpath_source ();
01050 
01051     if (s == "default path") return;
01052 
01053     if (CmtSystem::test_directory (w))
01054       {
01055         m_buffer += "path_append CMTPATH \"";
01056         m_buffer += w;
01057         m_buffer += "\" \n";
01058       }
01059   }
01060 
01061   void in (Project* p)
01062   {
01063     const cmt_string& w = p->get_cmtpath_pwd ();
01064     const cmt_string& s = p->get_cmtpath_source ();
01065 
01066     if (s == "default path") return;
01067 
01068     if (CmtSystem::test_directory (w))
01069       {
01070         m_buffer += "path_append CMTPATH \"";
01071         m_buffer += w;
01072         m_buffer += "\" \n";
01073       }
01074   }
01075 
01076   void post (Project* p)
01077   {
01078     //cerr << "Buffer = " << m_buffer << endl;
01079   }
01080 
01081 private:
01082   cmt_string& m_buffer;
01083 
01084 };
01085 
01086 //----------------------------------------------------------
01087 void Project::fill_cmtpaths (cmt_string& buffer)
01088 {
01089   /*
01090     Try to re-create all CMTPATH items from project definitions.
01091     The goal is to generate CMTPATH even if this EV was not pre-set
01092     which is the case when CMTPROJECTPATH is only used
01093    */
01094 
01095   VisitorForFillCMTPATH visitor (buffer);
01096 
01097   start_visit (visitor);
01098 }
01099 
01100 //----------------------------------------------------------
01101 Project::Project () : m_name ("")
01102 {
01103   clear ();
01104 }
01105 
01106 //----------------------------------------------------------
01107 const cmt_string& Project::get_name () const
01108 {
01109   return (m_name);
01110 }
01111 
01112 //----------------------------------------------------------
01113 const cmt_string& Project::get_release () const
01114 {
01115   return (m_release);
01116 }
01117 
01118 //----------------------------------------------------------
01119 const cmt_string& Project::get_container () const
01120 {
01121   return (m_container);
01122 }
01123 
01124 //----------------------------------------------------------
01125 const cmt_string& Project::get_container_version () const
01126 {
01127   return (m_container_version);
01128 }
01129 
01130 //----------------------------------------------------------
01131 const cmt_string& Project::get_cmtpath () const
01132 {
01133   return (m_cmtpath);
01134 }
01135 
01136 //----------------------------------------------------------
01137 const cmt_string& Project::get_cmtpath_pwd () const
01138 {
01139   return (m_cmtpath_pwd);
01140 }
01141 
01142 //----------------------------------------------------------
01143 const cmt_string& Project::get_cmtpath_source () const
01144 {
01145   return (m_cmtpath_source);
01146 }
01147 
01148 //----------------------------------------------------------
01149 int Project::get_children_size () const
01150 {
01151   return (m_children.size ());
01152 }
01153 
01154 //----------------------------------------------------------
01155 Project* Project::get_child (int index) const
01156 {
01157   if (index < 0) return (0);
01158   if (index >= m_children.size ()) return (0);
01159   return (m_children[index]);
01160 }
01161 
01162 //----------------------------------------------------------
01163 bool Project::visited () const
01164 {
01165   return (m_visited);
01166 }
01167 
01168 //----------------------------------------------------------
01169 void Project::set_name (const cmt_string& name)
01170 {
01171   m_name = name;
01172 }
01173 
01174 //----------------------------------------------------------
01175 void Project::set_release (const cmt_string& release)
01176 {
01177   m_release = release;
01178 }
01179 
01180 //----------------------------------------------------------
01181 void Project::set_container (const cmt_string& container)
01182 {
01183   m_container = container;
01184 }
01185 
01186 //----------------------------------------------------------
01187 void Project::set_container_version (const cmt_string& container_version)
01188 {
01189   m_container_version = container_version;
01190 }
01191 
01192 //----------------------------------------------------------
01193 void Project::set_cmtpath (const cmt_string& path)
01194 {
01195   m_cmtpath = path;
01196 }
01197 
01198 //----------------------------------------------------------
01199 void Project::set_cmtpath_pwd (const cmt_string& path)
01200 {
01201   m_cmtpath_pwd = path;
01202 }
01203 
01204 //----------------------------------------------------------
01205 void Project::set_cmtpath_source (const cmt_string& source)
01206 {
01207   m_cmtpath_source = source;
01208 }
01209 
01210 //----------------------------------------------------------
01211 void Project::clear ()
01212 {
01213   m_name = "";
01214   m_release = "";
01215   m_cmtpath = "";
01216   m_cmtpath_pwd = "";
01217   m_cmtpath_source = "";
01218 
01219   m_parents.clear ();
01220   m_children.clear ();
01221 
01222   m_configured = false;
01223 
01224   m_strategies.clear ();
01225 }
01226 
01227 //----------------------------------------------------------
01228 bool Project::has_parent (Project* p) const
01229 {
01230   if (p == 0) return (false);
01231   if (p == this) return (false);
01232 
01233   const cmt_string& name = p->get_name ();
01234 
01235   int i;
01236 
01237   for (i = 0; i < m_parents.size (); i++)
01238     {
01239       const Project* parent = m_parents[i];
01240       if (parent == 0) continue;
01241 
01242       if (parent->get_name () == name)
01243         {
01244           // registered as a parent
01245           return (true);
01246         }
01247 
01248       if (parent->has_parent (p))
01249         {
01250           // recurse
01251           return (true);
01252         }
01253     }
01254 
01255   return (false);
01256 }
01257 
01258 //----------------------------------------------------------
01259 bool Project::has_child (Project* p) const
01260 {
01261   if (p == 0) return (false);
01262   if (p == this) return (false);
01263 
01264   const cmt_string& name = p->get_name ();
01265 
01266   int i;
01267 
01268   for (i = 0; i < m_children.size (); i++)
01269     {
01270       const Project* child = m_children[i];
01271       if (child == 0) continue;
01272 
01273       if (child->get_name () == name)
01274         {
01275           // registered as a child
01276           return (true);
01277         }
01278 
01279       if (child->has_child (p))
01280         {
01281           // recurse
01282           return (true);
01283         }
01284     }
01285 
01286   return (false);
01287 }
01288 
01289 //----------------------------------------------------------
01290 void Project::add_parent (Project* p)
01291 {
01292   if (p == 0) return;
01293   if (p == this) return;
01294 
01295   //cerr << "Adding parent " << p->get_name () << " to " << m_name << endl;
01296 
01297   if (has_child (p)) return;
01298   if (has_parent (p)) return;
01299 
01300   m_parents.push_back (p);
01301 }
01302 
01303 //----------------------------------------------------------
01304 void Project::add_child (Project* p)
01305 {
01306   if (p == 0) return;
01307   if (p == this) return;
01308 
01309   if (has_child (p)) return;
01310   if (has_parent (p)) return;
01311 
01312   m_children.push_back (p);
01313 }
01314 
01315 //----------------------------------------------------------
01316 void Project::configure ()
01317 {
01318   if (m_configured) return;
01319   m_configured = true;
01320 
01321   set_default_strategy ("SetupConfig");
01322   set_default_strategy ("SetupRoot");
01323   set_default_strategy ("SetupCleanup");
01324   set_default_strategy ("BuildPrototypes");
01325   set_default_strategy ("InstallArea");
01326 }
01327 
01331 void Project::container_action (const cmt_string& name, const cmt_string& version)
01332 {
01333   //cerr << "Container action " << name << " " << version << endl;
01334 
01335   set_container (name);
01336   set_container_version (version);
01337 }
01338 
01342 void Project::use_action (const cmt_string& name, const cmt_string& release)
01343 {
01344   //cerr << "Use action " << name << " " << release << endl;
01345 
01346   // A project with its release is specified
01347   //
01348   // Is this project already visible?
01349   // If not: look for it
01350   //   + get CMTPROJECTPATH
01351   //   + search from all entries of CMTPROJECTPATH : p(i)/<name>/<release>
01352   //   + when found, this should become a new CMTPATH entry
01353   //   +             the new project is then parsed ... etc...
01354 
01355   cmt_string cmtprojectpath = CmtSystem::getenv ("CMTPROJECTPATH");
01356   cmt_string sep;
01357   sep = CmtSystem::path_separator ();
01358 
01359   //cerr << "cmtprojectpath = " << cmtprojectpath << endl;
01360   CmtSystem::cmt_string_vector items;
01361   CmtSystem::split (cmtprojectpath, sep, items);
01362 
01363   bool found = false;
01364 
01365   for (int i = 0; i < items.size (); i++)
01366     {
01367       const cmt_string& item = items[i];
01368       cmt_string p = item;
01369       p += CmtSystem::file_separator ();
01370       p += name;
01371       p += CmtSystem::file_separator ();
01372       p += release;
01373 
01374       if (CmtSystem::test_directory (p))
01375         {
01376           //cerr << "Project directory " << p << " exists " << endl;
01377 
01378           found = true;
01379 
01380           IProjectFactory& factory = ProjectFactory::instance ();
01381 
01382           factory.create_project (name, p, "ProjectPath", this);
01383 
01384           break;
01385         }
01386     }
01387 
01388   if (!found)
01389     {
01390       Project* p = Project::find_by_name (name);
01391 
01392       if (p != 0)
01393         {
01394           found = true;
01395 
01396           p->add_parent (this);
01397           add_child (p);
01398 
01399           update_strategies_from_children ();
01400         }
01401     }
01402 
01403   if (!found && (cmtprojectpath != ""))
01404     {
01405       cerr << "#CMT> Project " << name << " " << release << " requested by " << m_name << " not found in CMTPROJECTPATH" << endl;
01406     }
01407 }
01408 
01409 
01410 //----------------------------------------------------------
01411 Project& Project::operator = (const Project& other)
01412 {
01413   m_name = other.m_name;
01414   m_cmtpath = other.m_cmtpath;
01415   m_cmtpath_pwd = other.m_cmtpath_pwd;
01416   m_cmtpath_source = other.m_cmtpath_source;
01417 
01418   return (*this);
01419 }
01420 
01421 //----------------------------------------------------------
01422 bool Project::operator == (const cmt_string& name) const
01423 {
01424   return ((m_name == name));
01425 }
01426 
01427 //----------------------------------------------------------
01428 bool Project::operator != (const cmt_string& name) const
01429 {
01430   return ((m_name != name));
01431 }
01432 
01433 //----------------------------------------------------------
01434 void Project::show ()
01435 {
01436   static int level = 0;
01437 
01438   bool is_current = false;
01439 
01440   cmt_string here = CmtSystem::pwd ();
01441 
01442   if (here.find (m_cmtpath) == 0) 
01443     {
01444       if (m_cmtpath_source != "default path")
01445         {
01446           is_current = true;
01447         }
01448     }
01449 
01450   for (int tab = 0; tab < level; tab++) cout << "  ";
01451   cout << m_name << " " << m_release << " (in " << m_cmtpath << ")";
01452 
01453   if (is_current) cout << " (current)";
01454 
01455   int i;
01456 
01457   for (i = 0; i < m_parents.size (); i++)
01458     {
01459       Project* p = m_parents[i];
01460       if (p == 0) continue;
01461       cout << " P=" << p->get_name ();
01462     }
01463 
01464   for (i = 0; i < m_children.size (); i++)
01465     {
01466       Project* p = m_children[i];
01467       if (p == 0) continue;
01468       cout << " C=" << p->get_name ();
01469     }
01470 
01471   cout << endl;
01472 
01473   if (m_visited) return;
01474 
01475   m_visited = true;
01476 
01477   for (i = 0; i < m_children.size (); i++)
01478     {
01479       Project* p = m_children[i];
01480       if (p == 0) continue;
01481       level++;
01482       p->show ();
01483       level--;
01484     }
01485 }
01486 
01487 
01488 //----------------------------------------------------------
01489 void Project::show_specified_strategies () const
01490 {
01491   int i;
01492 
01493   for (i = 0; i < m_strategies.size (); i++)
01494     {
01495       const Strategy& s = m_strategies[i];
01496       if (s.m_specified)
01497         {
01498           const StrategyDef* def = s.m_definition;
01499  
01500           cout << "# Project " << m_name
01501                << " sets " << def->m_keyword
01502                << " strategy to " << ((s.m_value) ? def->m_on_value : def->m_off_value);
01503 
01504           if (s.m_context != "")
01505             {
01506               cout << " (from package " << s.m_context << ")";
01507             }
01508 
01509           cout << endl;
01510         }
01511     }
01512 }
01513 
01514 //----------------------------------------------------------
01515 bool Project::has_strategy (const StrategyDef* definition) const
01516 {
01517   int i;
01518 
01519   for (i = 0; i < m_strategies.size (); i++)
01520     {
01521       const Strategy& s = m_strategies[i];
01522       if (s.m_definition == definition)
01523         {
01524           return (true);
01525         }
01526     }
01527 
01528   return (false);
01529 }
01530 
01531 //----------------------------------------------------------
01532 bool Project::get_strategy (const cmt_string& name) const
01533 {
01534   static StrategyMgr& mgr = StrategyMgr::instance ();
01535 
01536   StrategyDef* def = mgr.find_strategy (name);
01537   if (def == 0)
01538     {
01539       cerr << "#CMT> strategy " << name << " undefined" << endl;
01540       return (false);
01541     }
01542 
01543   return (get_strategy (def));
01544 }
01545 
01546 //----------------------------------------------------------
01547 bool Project::is_specified (const StrategyDef* definition) const
01548 {
01549   int i;
01550 
01551   for (i = 0; i < m_strategies.size (); i++)
01552     {
01553       Strategy& s = m_strategies[i];
01554       if (s.m_definition == definition)
01555         {
01556           // This strategy is applied in this project
01557           return (s.m_specified);
01558         }
01559     }
01560 
01561   // This strategy is not applied in this project
01562   return (false);
01563 }
01564 
01565 //----------------------------------------------------------
01566 bool Project::get_strategy (const StrategyDef* def) const
01567 {
01568   int i;
01569 
01570   for (i = 0; i < m_strategies.size (); i++)
01571     {
01572       Strategy& s = m_strategies[i];
01573       if (s.m_definition == def)
01574         {
01575           // This strategy is applied in this project
01576           if (s.m_specified)
01577             {
01578               return (s.m_specified_value);
01579             }
01580           return (s.m_value);
01581         }
01582     }
01583 
01584   // This strategy is not applied in this project
01585   return (def->m_default_value);
01586 }
01587 
01588 //----------------------------------------------------------
01589 void Project::set_default_strategy (const cmt_string& name)
01590 {
01591   static StrategyMgr& mgr = StrategyMgr::instance ();
01592 
01593   StrategyDef* def = mgr.find_strategy (name);
01594   if (def == 0)
01595     {
01596       cerr << "#CMT> strategy " << name << " undefined" << endl;
01597       return;
01598     }
01599 
01600   update_strategy (def, def->m_default_value);
01601 }
01602 
01603 
01604 //----------------------------------------------------------
01605 void Project::set_strategy (const cmt_string& name, const cmt_string& value, const cmt_string& context)
01606 {
01607   static StrategyMgr& mgr = StrategyMgr::instance ();
01608 
01609   StrategyDef* def = mgr.find_strategy (name);
01610   if (def == 0)
01611     {
01612       cerr << "#CMT> strategy " << name << " undefined" << endl;
01613       return;
01614     }
01615 
01616   bool b_value = false;
01617 
01618   if (value == def->m_on_value)
01619     {
01620       b_value = true;
01621     }
01622   else if (value == def->m_off_value)
01623     {
01624       b_value = false;
01625     }
01626   else
01627     {
01628       cerr << "#CMT> requested strategy value " << value << " undefined in strategy " << name << endl;
01629       return;
01630     }
01631 
01632   set_strategy (def, b_value, context);
01633 }
01634 
01635 //----------------------------------------------------------
01636 void Project::set_strategy (StrategyDef* definition, bool b_value, const cmt_string& context)
01637 {
01638   bool need_strategy = true;
01639 
01640   int i;
01641 
01642   for (i = 0; i < m_strategies.size (); i++)
01643     {
01644       Strategy& s = m_strategies[i];
01645       if (s.m_definition == definition)
01646         {
01647           // This strategy is already applied in this project. Let's change it's value
01648           s.set (definition, b_value, get_name ());
01649           if (context != "")
01650             {
01651               if (s.m_context != "") s.m_context += " ";
01652               s.m_context += context;
01653             }
01654           need_strategy = false;
01655           break;
01656         }
01657     }
01658 
01659   if (need_strategy)
01660     {
01661       // This strategy is not yet applied in this project.
01662 
01663       Strategy& s = m_strategies.add ();
01664       s.clear ();
01665       s.set (definition, b_value, get_name ());
01666       s.m_context = context;
01667     }
01668   
01669   for (i = 0; i < m_parents.size (); i++)
01670     {
01671       Project* project = m_parents[i];
01672 
01673       project->update_strategy (definition, b_value);
01674     }
01675 }
01676 
01685 void Project::update_strategy (StrategyDef* definition, bool b_value)
01686 {
01687   bool need_strategy = true;
01688   bool specified = false;
01689 
01690   int i;
01691 
01692   for (i = 0; i < m_strategies.size (); i++)
01693     {
01694       Strategy& s = m_strategies[i];
01695       if (s.m_definition == definition)
01696         {
01697           need_strategy = false;
01698 
01699           if (!s.m_specified)
01700             {
01701               // This strategy is already applied in this project. Let's change it's value
01702               s.update (definition, b_value, get_name ());
01703             }
01704           else
01705             {
01706               specified = true;
01707             }
01708           break;
01709         }
01710     }
01711 
01712   if (need_strategy)
01713     {
01714       // This strategy is not yet applied in this project.
01715 
01716       Strategy& s = m_strategies.add ();
01717       s.clear ();
01718       s.update (definition, b_value, get_name ());
01719     }
01720 
01721   if (!specified)
01722     {
01723       for (i = 0; i < m_parents.size (); i++)
01724         {
01725           Project* project = m_parents[i];
01726 
01727           project->update_strategy (definition, b_value);
01728         }
01729     }
01730 }
01731 
01738 void Project::update_strategy_from_children (StrategyDef* definition)
01739 {
01740   // If this strategy is specified we don't care what happens from the children
01741 
01742   //cerr << "Updating strategy " << definition->m_name << " from children for project " << m_name << endl;
01743 
01744   int i;
01745 
01746   for (i = 0; i < m_strategies.size (); i++)
01747     {
01748       Strategy& s = m_strategies[i];
01749       if (s.m_definition == definition)
01750         {
01751           // This strategy is applied in this project.
01752 
01753           if (s.m_specified)
01754             {
01755               // There will be no impact since the strategy is specified
01756 
01757               //cerr << "This strategy is specified in this project" << endl;
01758               return;
01759             }
01760 
01761           break;
01762         }
01763     }
01764 
01765   // The strategy is not specified locally so we will now figure out
01766   // which strategy has to be considered from the mixture of specifications
01767   // from all children.
01768 
01769   // Algorithm:
01770   // - We consider children by pairs
01771   // - a child that specifies its strategy wins over a child that does not
01772   // - when the two children have the same level of priority we consider the priority value
01773 
01774   Project* selected = 0;
01775   bool selected_is_specified = false;
01776   bool selected_value = definition->m_default_value;
01777 
01778   for (i = 0; i < m_children.size (); i++)
01779     {
01780       Project* p = m_children[i];
01781 
01782       //cerr << "Checking strategy for child " << p->get_name () << endl;
01783 
01784       bool is_specified = p->is_specified (definition);
01785       bool value = p->get_strategy (definition);
01786 
01787       if (selected == 0)
01788         {
01789           selected = p;
01790           selected_is_specified = is_specified;
01791           selected_value = value;
01792           continue;
01793         }
01794 
01795       if (is_specified == selected_is_specified)
01796         {
01797           if (selected_value != value)
01798             {
01799               // same level of priority but different values -> we must decide
01800               bool priority_value = definition->m_priority_value;
01801               if (value == priority_value)
01802                 {
01803                   selected = p;
01804                   selected_is_specified = is_specified;
01805                   selected_value = value;
01806                 }
01807             }
01808         }
01809       else
01810         {
01811           if (is_specified)
01812             {
01813               selected = p;
01814               selected_is_specified = is_specified;
01815               selected_value = value;
01816             }
01817         }
01818     }
01819 
01820   update_strategy (definition, selected_value);  
01821 }
01822 
01829 void Project::update_strategies_from_children ()
01830 {
01831   StrategyDef::StrategyDefs& defs = StrategyMgr::get_definitions ();
01832 
01833   //cerr << "Updating strategies from children for project " << m_name << endl;
01834 
01835   int i;
01836 
01837   for (i = 0; i < defs.size (); i++)
01838     {
01839       StrategyDef* def = defs[i];
01840       
01841       update_strategy_from_children (def);
01842     }
01843 
01844   for (i = 0; i < m_parents.size (); i++)
01845     {
01846       Project* p = m_parents[i];
01847       p->update_strategies_from_children ();
01848     }
01849 }
01850 
01854 StrategyMgr& StrategyMgr::instance ()
01855 {
01856   static StrategyMgr me;
01857   return (me);
01858 }
01859 
01864 StrategyMgr::StrategyMgr ()
01865 {
01866   m_defs.clear ();
01867 
01868   StrategyDef* s;
01869 
01870   s = new StrategyDef;
01871   s->m_keyword = "build";
01872   s->m_name = "BuildPrototypes";
01873   s->m_on_value = "prototypes";
01874   s->m_off_value = "no_prototypes";
01875   s->m_default_value = true;
01876   s->m_priority_value = false;
01877 
01878   m_defs.push_back (s);
01879 
01880   s = new StrategyDef;
01881   s->m_keyword = "build";
01882   s->m_name = "InstallArea";
01883   s->m_on_value = "with_installarea";
01884   s->m_off_value = "without_installarea";
01885   s->m_default_value = false;
01886   s->m_priority_value = true;
01887 
01888   m_defs.push_back (s);
01889 
01890   s = new StrategyDef;
01891   s->m_keyword = "setup";
01892   s->m_name = "SetupConfig";
01893   s->m_on_value = "config";
01894   s->m_off_value = "no_config";
01895   s->m_default_value = true;
01896   s->m_priority_value = false;
01897 
01898   m_defs.push_back (s);
01899 
01900   s = new StrategyDef;
01901   s->m_keyword = "setup";
01902   s->m_name = "SetupRoot";
01903   s->m_on_value = "root";
01904   s->m_off_value = "no_root";
01905   s->m_default_value = true;
01906   s->m_priority_value = false;
01907 
01908   m_defs.push_back (s);
01909 
01910   s = new StrategyDef;
01911   s->m_keyword = "setup";
01912   s->m_name = "SetupCleanup";
01913   s->m_on_value = "cleanup";
01914   s->m_off_value = "no_cleanup";
01915   s->m_default_value = true;
01916   s->m_priority_value = false;
01917 
01918   m_defs.push_back (s);
01919 }
01920 
01924 StrategyDef* StrategyMgr::find_strategy (const cmt_string& name)
01925 {
01926   static StrategyMgr& me = instance ();
01927 
01928   int i;
01929 
01930   for (i = 0; i < me.m_defs.size (); i++)
01931     {
01932       StrategyDef* def = me.m_defs[i];
01933       if (def->m_name == name)
01934         {
01935           return (def);
01936         }
01937     }
01938 
01939   return (0);
01940 }
01941 
01945 bool StrategyMgr::get_default_strategy (const cmt_string& name)
01946 {
01947   StrategyDef* def = find_strategy (name);
01948   if (def == 0) return (false);
01949   return (def->m_default_value);
01950 }
01951 
01956 bool StrategyMgr::get_priority_strategy (const cmt_string& name)
01957 {
01958   StrategyDef* def = find_strategy (name);
01959   if (def == 0) return (false);
01960   return (def->m_priority_value);
01961 }
01962 
01966 StrategyDef::StrategyDefs& StrategyMgr::get_definitions ()
01967 {
01968   static StrategyMgr& me = instance ();
01969 
01970   return (me.m_defs);
01971 }
01972 
01973 //-----------------------------------------------------------
01974 Strategy::Strategy ()
01975 {
01976   clear ();
01977 }
01978 
01979 //-----------------------------------------------------------
01980 void Strategy::clear ()
01981 {
01982   m_definition = 0;
01983   m_specified = false;
01984   m_specified_value = false;
01985   m_value = false;
01986   m_on_tag = 0;
01987   m_off_tag = 0;
01988 }
01989 
01994 void Strategy::set (StrategyDef* definition, bool value, const cmt_string& project_name)
01995 {
01996   //cerr << "Setting strategy " << definition->m_name << " for project " << project_name << " to " << value << endl;
01997 
01998   m_definition = definition;
01999   m_specified = true;
02000   m_specified_value = value;
02001 
02002   update (definition, value, project_name);
02003 }
02004 
02010 void Strategy::update (StrategyDef* definition, bool value, const cmt_string& project_name)
02011 {
02012   //cerr << "Updating strategy " << definition->m_name << " for project " << project_name << " to " << value << endl;
02013 
02014   m_value = value;
02015   m_definition = definition;
02016 
02017   cmt_string to_tag_name = project_name;
02018   cmt_string to_untag_name = project_name;
02019 
02020   to_tag_name += "_";
02021   to_untag_name += "_";
02022 
02023   if (m_value)
02024     {
02025       to_tag_name += m_definition->m_on_value;
02026       to_untag_name += m_definition->m_off_value;
02027     }
02028   else
02029     {
02030       to_tag_name += m_definition->m_off_value;
02031       to_untag_name += m_definition->m_on_value;
02032     }
02033 
02034   m_on_tag = Tag::find (to_tag_name);
02035   m_off_tag = Tag::find (to_untag_name);
02036 
02037   if (m_on_tag == 0) 
02038     {
02039       m_on_tag = Tag::add (to_tag_name, PriorityConfig, "PROJECT", 0);
02040       m_off_tag = Tag::add (to_untag_name, PriorityConfig, "PROJECT", 0);
02041 
02042       m_on_tag->add_tag_exclude (m_off_tag);
02043       m_off_tag->add_tag_exclude (m_on_tag);
02044     }
02045 
02046   m_off_tag->unmark ();
02047   m_on_tag->mark ();
02048 }
02049 
02050 const cmt_string& StrategyDef::get_default_value () const
02051 {
02052   if (m_default_value)
02053     {
02054       return (m_on_value);
02055     }
02056   else
02057     {
02058       return (m_off_value);
02059     }
02060 }
02061 

Generated on Mon May 2 10:25:05 2005 for CMT by doxygen 1.3.5