00001
00002
00003
00004
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
00113
00114
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
00128
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
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
00179
00180 return (result);
00181 }
00182
00183
00184
00185
00186
00187
00188
00189
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
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
00266
00267 if (here.find (pwd) == 0) is_current = true;
00268
00269 cmt_string text;
00270
00271
00272
00273
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
00319
00320
00321
00322
00323
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
00334
00335
00336 if (get_release_from_path (items, compressed_path, specified_name, name, release))
00337 {
00338
00339
00340 }
00341 else
00342 {
00343
00344
00345
00346
00347
00348
00349
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
00360
00361
00362 if (get_release_from_path (items, compressed_path, specified_name, name, release))
00363 {
00364
00365
00366 }
00367 else
00368 {
00369
00370
00371
00372
00373
00374
00375
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
00386
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
00400 }
00401 else if (get_release_from_path (items, compressed_path, project_name, name, release))
00402 {
00403
00404 }
00405 else
00406 {
00407
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
00426
00427 if (get_release_from_path (items, compressed_path, project_name, name, release))
00428 {
00429
00430
00431
00432 }
00433 else
00434 {
00435
00436
00437
00438
00439
00440
00441
00442
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
00454
00455
00456
00457
00458
00459
00460
00461
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
00474
00475
00476 if (get_release_from_path (items, compressed_path, specified_name, name, release))
00477 {
00478
00479
00480 }
00481 else
00482 {
00483
00484
00485
00486
00487
00488
00489
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
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
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
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
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
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
00738
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
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
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
01079 }
01080
01081 private:
01082 cmt_string& m_buffer;
01083
01084 };
01085
01086
01087 void Project::fill_cmtpaths (cmt_string& buffer)
01088 {
01089
01090
01091
01092
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
01245 return (true);
01246 }
01247
01248 if (parent->has_parent (p))
01249 {
01250
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
01276 return (true);
01277 }
01278
01279 if (child->has_child (p))
01280 {
01281
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
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
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
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355 cmt_string cmtprojectpath = CmtSystem::getenv ("CMTPROJECTPATH");
01356 cmt_string sep;
01357 sep = CmtSystem::path_separator ();
01358
01359
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
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
01557 return (s.m_specified);
01558 }
01559 }
01560
01561
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
01576 if (s.m_specified)
01577 {
01578 return (s.m_specified_value);
01579 }
01580 return (s.m_value);
01581 }
01582 }
01583
01584
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
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
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
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
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
01741
01742
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
01752
01753 if (s.m_specified)
01754 {
01755
01756
01757
01758 return;
01759 }
01760
01761 break;
01762 }
01763 }
01764
01765
01766
01767
01768
01769
01770
01771
01772
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
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
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
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
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
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