00001 #include <stdlib.h>
00002 #include <stdio.h>
00003
00004 #include "cmt_cvs.h"
00005 #include "cmt_awk.h"
00006
00024 class Grep : public Awk
00025 {
00026 public:
00027
00028 void begin ();
00029 void filter (const cmt_string& line);
00030 const cmt_string& result () const;
00031
00032 private:
00033 cmt_string m_result;
00034 };
00035
00048 class Cut : public Awk
00049 {
00050 public:
00051 Cut (int field);
00052 void begin ();
00053 void filter (const cmt_string& line);
00054 const cmt_string& result () const;
00055
00056 private:
00057 cmt_string m_result;
00058 int m_field;
00059 };
00060
00067 class History
00068 {
00069 public:
00070 static History& instance ();
00071 void clear ();
00072 void install (const cmt_string& line);
00073 bool is_installed (const cmt_string& line);
00074
00075 private:
00076 History ();
00077
00078 cmt_string m_installed;
00079 };
00080
00087 class RecursivePass1 : public Awk
00088 {
00089 public:
00090
00091 void begin ();
00092 void filter (const cmt_string& line);
00093 const cmt_string& result () const;
00094
00095 private:
00096 cmt_string m_result;
00097 bool m_first;
00098 };
00099
00106 class CvsImplementation;
00107 class RecursivePass2 : public Awk
00108 {
00109 public:
00110 RecursivePass2 (CvsImplementation& cvs);
00111 void begin ();
00112 void filter (const cmt_string& line);
00113
00114 private:
00115 CvsImplementation& m_cvs;
00116 };
00117
00124 class CvsImplementation
00125 {
00126 public:
00127
00128 void filter_list (cmt_string& text, const cmt_regexp& exp)
00129 {
00130 CmtSystem::cmt_string_vector list;
00131
00132 CmtSystem::split (text, " ", list);
00133
00134 int i;
00135
00136 text = "";
00137
00138 for (i = 0; i < list.size (); i++)
00139 {
00140 const cmt_string& s = list[i];
00141 if (exp.match (s))
00142 {
00143 if (i > 0) text += " ";
00144 text += s;
00145 }
00146 }
00147 }
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 void show_cvs_infos (const cmt_string& module)
00171 {
00172 cmt_string out;
00173
00174 if (module == "")
00175 {
00176 cout << "# cmt cvs needs a module name" << endl;
00177 return;
00178 }
00179
00180 cmt_string home_dir = CmtSystem::pwd ();
00181
00182
00183
00184
00185 cmt_string tmp_dir = CmtSystem::getenv ("TMPDIR");
00186 if (tmp_dir == "")
00187 {
00188 tmp_dir = CmtSystem::file_separator ();
00189 tmp_dir += "tmp";
00190 }
00191
00192 if (!CmtSystem::cd (tmp_dir))
00193 {
00194 tmp_dir = home_dir;
00195 }
00196
00197 tmp_dir += CmtSystem::file_separator ();
00198 tmp_dir += "cmtcvs";
00199 {
00200 cmt_string temp = CmtSystem::get_temporary_name ();
00201 CmtSystem::basename (temp, temp);
00202 tmp_dir += temp;
00203 }
00204
00205 if (!CmtSystem::test_directory (tmp_dir))
00206 {
00207 if (!CmtSystem::mkdir (tmp_dir))
00208 {
00209 cout << "# Cannot create the temporary directory ["
00210 << tmp_dir << "]" << endl;
00211 return;
00212 }
00213 }
00214
00215
00216
00217 if (!CmtSystem::cd (tmp_dir))
00218 {
00219 cout << "# Cannot move to the temporary directory " << tmp_dir << endl;
00220 return;
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 if (!CmtSystem::test_directory (".cmtcvsinfos"))
00238 {
00239 CmtSystem::mkdir (".cmtcvsinfos");
00240 }
00241
00242 CmtSystem::cd (".cmtcvsinfos");
00243
00244 cmt_string cvsroot;
00245
00246 CmtSystem::get_cvsroot (cvsroot);
00247
00248 cmt_string command;
00249
00250 command = "cvs";
00251 if (cvsroot != "")
00252 {
00253 command += " -d ";
00254 command += cvsroot;
00255 }
00256 command += " -Q import -m cmt ";
00257 if (m_cmtcvstest)
00258 {
00259 command += ".cmtcvsinfos/cmtcvstest";
00260 }
00261 else
00262 {
00263 command += ".cmtcvsinfos";
00264 }
00265 command += "/";
00266 command += module;
00267 command += " CMT v1";
00268
00269 CmtSystem::execute (command, out);
00270
00271
00272
00284 Grep grep;
00285
00286 grep.run (out, "error=");
00287
00288 if (grep.result () != "")
00289 {
00290 error_info = grep.result ();
00291 error_info.replace ("error=", "");
00292 }
00293 else
00294 {
00295 error_info = "";
00296 }
00297
00298 grep.run (out, "tags_top=");
00299
00300 if (grep.result () != "")
00301 {
00302 tags_top_info = grep.result ();
00303 tags_top_info.replace ("tags_top=", "");
00304 }
00305 else
00306 {
00307 tags_top_info = "";
00308 }
00309
00310 grep.run (out, "tags=");
00311
00312 if (grep.result () != "")
00313 {
00314 tags_info = grep.result ();
00315 tags_info.replace ("tags=", "");
00316 }
00317 else
00318 {
00319 tags_info = "";
00320 }
00321
00322 grep.run (out, "cvsversions_top=");
00323
00324 if (grep.result () != "")
00325 {
00326 cvsversions_top_info = grep.result ();
00327 cvsversions_top_info.replace ("cvsversions_top=", "");
00328 }
00329 else
00330 {
00331 cvsversions_top_info = "";
00332 }
00333
00334 grep.run (out, "cvsversions=");
00335
00336 if (grep.result () != "")
00337 {
00338 cvsversions_info = grep.result ();
00339 cvsversions_info.replace ("cvsversions=", "");
00340 }
00341 else
00342 {
00343 cvsversions_info = "";
00344 }
00345
00346 cmt_string tag_filter = CmtSystem::getenv ("CMTCVSTAGFILTER");
00347
00348 if (tag_filter != "")
00349 {
00350 cmt_string package;
00351 CmtSystem::basename (module, package);
00352
00353 cmt_string pattern = "<package>";
00354
00355 tag_filter.replace_all (pattern, package);
00356
00357 cmt_regexp exp (tag_filter);
00358
00359 cmt_string text;
00360
00361 filter_list (tags_top_info, exp);
00362 filter_list (tags_info, exp);
00363 filter_list (cvsversions_top_info, exp);
00364 filter_list (cvsversions_info, exp);
00365 }
00366
00367 if (m_cmtcvstest)
00368 {
00369 cout << "## tags_top_info=" << tags_top_info << endl;
00370 cout << "## tags_info=" << tags_info << endl;
00371 cout << "## cvsversions_top_info=" << cvsversions_top_info << endl;
00372 cout << "## cvsversions_info=" << cvsversions_info << endl;
00373 }
00374
00375 grep.run (out, "branches=");
00376
00377 if (grep.result () != "")
00378 {
00379 branches_info = grep.result ();
00380 branches_info.replace ("branches=", "");
00381 }
00382 else
00383 {
00384 branches_info = "";
00385 }
00386
00387 grep.run (out, "subpackages=");
00388
00389 if (grep.result () != "")
00390 {
00391 subpackages_info = grep.result ();
00392 subpackages_info.replace ("subpackages=", "");
00393 }
00394 else
00395 {
00396 subpackages_info = "";
00397 }
00398
00399 CmtSystem::cd (home_dir);
00400
00401 CmtSystem::remove_directory (tmp_dir);
00402 }
00403
00404 void show_cvs_infos (const cmt_string& offset,
00405 const cmt_string& module)
00406 {
00407 cmt_string full_name;
00408
00409 if (offset != "")
00410 {
00411 full_name = offset;
00412 full_name += "/";
00413 full_name.replace_all ("//", "/");
00414 }
00415
00416 full_name += module;
00417
00418 show_cvs_infos (full_name);
00419 }
00420
00421
00422
00423
00424 void filter_dir (cmt_string& d)
00425 {
00426 while (true)
00427 {
00428 int pos = d.find ("/../");
00429 if (pos == cmt_string::npos) break;
00430
00431 int slash = d.find ("/");
00432 if (slash < pos)
00433 {
00434
00435
00436
00437
00438
00439
00440
00441
00442 d.erase (slash + 1, pos + 3 - slash);
00443 }
00444 else
00445 {
00446
00447
00448
00449
00450
00451
00452
00453 d.erase (0, pos + 1 + 3);
00454 }
00455 }
00456 }
00457
00466 bool match_version_request (const cmt_string& text,
00467 const cmt_regexp& version_exp,
00468 cmt_string& version)
00469 {
00470 CmtSystem::cmt_string_vector vs;
00471
00472 CmtSystem::split (text, " \t", vs);
00473
00474 version = "";
00475
00476 for (int i = 0; i < vs.size (); i++)
00477 {
00478 const cmt_string& vv = vs[i];
00479
00480 if (version_exp.match (vv))
00481 {
00482 version = vv;
00483 return (true);
00484 }
00485 }
00486
00487 return (false);
00488 }
00489
00490 bool get_version (const cmt_string& prefix,
00491 const cmt_string& package,
00492 const cmt_string& version_request,
00493 cmt_string& module,
00494 cmt_string& version,
00495 bool& at_head)
00496 {
00497 Grep grep;
00498 cmt_string topversions;
00499 cmt_string versions;
00500 cmt_string requested_version = version_request;
00501
00502 at_head = false;
00503
00504 module = "";
00505
00506 if (prefix != "")
00507 {
00508 module = prefix;
00509 module += "/";
00510 module.replace_all ("//", "/");
00511 }
00512
00513 module += package;
00514
00529
00530
00531 show_cvs_infos (module);
00532
00533 if (error_info != "")
00534 {
00535 versions = "";
00536 cout << "# Package " << package << " not found in ${CVSROOT}" << endl;
00537 return (false);
00538 }
00539
00540 versions = tags_top_info;
00541
00542 cmt_string v = version_request;
00543
00544 if (version_request.find ("*") != cmt_string::npos)
00545 {
00546 v.replace_all ("*", ".*");
00547 }
00548 else
00549 {
00550 v += "$";
00551 }
00552
00553 if (m_cmtcvstest) cout << "## (version expression is " << v << ")" << endl;
00554
00555 cmt_regexp version_exp (v);
00556
00557 if (!match_version_request (versions, version_exp, version))
00558 {
00559 if (m_cmtcvstest) cout << "## (no match in " << versions << ")" << endl;
00560
00561
00562
00563 versions = tags_info;
00564
00565 if (!match_version_request (versions, version_exp, version))
00566 {
00567 if (m_cmtcvstest) cout << "## (no match in " << versions << ")" << endl;
00568
00569 version = requested_version;
00570 int pos = 0;
00571 if ((pos = version.find ("*")) != cmt_string::npos)
00572 {
00573
00574
00575
00576
00577
00578
00579
00580
00581 if (pos > 0)
00582 {
00583 char letter = version[pos-1];
00584
00585 static const cmt_string digits = "0123456789";
00586
00587 if (digits.find (letter) == cmt_string::npos)
00588 {
00589
00590 version.replace ("*", "0");
00591 }
00592 else
00593 {
00594
00595 version.replace ("*", "");
00596 }
00597 }
00598 else
00599 {
00600
00601 version = "v0";
00602 }
00603 }
00604 at_head = true;
00605 }
00606 else
00607 {
00608 if (m_cmtcvstest) cout << "## (match in non head " << versions << ")" << endl;
00609
00610 at_head = false;
00611 }
00612 }
00613 else
00614 {
00615 if (m_cmtcvstest) cout << "## (match in head " << versions << ")" << endl;
00616
00617 at_head = true;
00618 }
00619
00624 return (true);
00625 }
00626
00627 cmt_string build_version_directory (const cmt_string& prefix,
00628 const cmt_string& package,
00629 const cmt_string& version)
00630 {
00631 cmt_string dir = m_home_dir;
00632
00633 if (m_checkout_dir != "")
00634 {
00635 dir += CmtSystem::file_separator ();
00636 dir += m_checkout_dir;
00637 }
00638
00639 dir += CmtSystem::file_separator ();
00640 dir += prefix;
00641 dir += CmtSystem::file_separator ();
00642 dir += package;
00643 dir += CmtSystem::file_separator ();
00644 dir += version;
00645
00646 {
00647 cmt_string fs = CmtSystem::file_separator ();
00648 cmt_string dfs = fs;
00649 dfs += fs;
00650
00651 dir.replace_all (dfs, fs);
00652 }
00653
00654 return (dir);
00655 }
00656
00657 bool really_checkout_package (const cmt_string& prefix,
00658 const cmt_string& package,
00659 const cmt_string& version,
00660 const cmt_string& module,
00661 const cmt_string& basedir,
00662 bool at_head)
00663 {
00664 cmt_string dir = basedir;
00665 cmt_string out;
00666
00667 cout << "# ================= working on package " << package
00668 << " version " << version;
00669
00670 if (at_head) cout << " (At head) ";
00671
00672 {
00673 cmt_string full_prefix;
00674
00675 full_prefix = m_offset;
00676 full_prefix += prefix;
00677
00678 cmt_string echo_ppath;
00679
00680 if (full_prefix != "")
00681 {
00682 echo_ppath = " path ";
00683 echo_ppath += prefix;
00684 }
00685
00686 cout << echo_ppath << endl;
00687 }
00688
00689 CmtSystem::dirname (dir, dir);
00690
00691 if (!CmtSystem::mkdir (dir))
00692 {
00693 return (false);
00694 }
00695
00696 CmtSystem::cd (dir);
00697
00698 cout << " # get top files " << endl;
00699
00700 cmt_string command = "cvs -Q co -P -l ";
00701 if (!at_head)
00702 {
00703 command += "-r ";
00704 command += version;
00705 }
00706 command += " -d ";
00707 command += version;
00708 command += " ";
00709 command += module;
00710
00711 if (m_cmtcvstest)
00712 {
00713 cmt_string cvsroot;
00714
00715 CmtSystem::get_cvsroot (cvsroot);
00716
00717 cout << "## cvsroot=" << cvsroot << " command[" << command << "]" << endl;
00718 }
00719
00720 int status = CmtSystem::execute (command, out);
00721
00722
00723
00724 if (!CmtSystem::cd (version))
00725 {
00726 CmtSystem::mkdir (version);
00727 if (!CmtSystem::cd (version))
00728 {
00729 cout << "# Error creating the version directory :" << version << endl;
00730 cout << "#---------------------------------------------------------" << endl;
00731 return (false);
00732 }
00733 }
00734
00735 dir += CmtSystem::file_separator ();
00736 dir += version;
00737
00738 cmt_string file_name;
00739 cmt_string text;
00740
00741 cmt_string branches = CmtSystem::getenv ("CMTCVSBRANCHES");
00742
00743 if (branches == "")
00744 {
00745 branches = branches_info;
00746 }
00747
00748 CmtSystem::cmt_string_vector branch_vector;
00749
00750 CmtSystem::split (branches, " \t", branch_vector);
00751
00752 int i;
00753
00754 cout << " # get branches " << branches << endl;
00755
00756 command = "";
00757
00758 file_name = "CVS";
00759 file_name += CmtSystem::file_separator ();
00760 file_name += "Entries";
00761
00762 if (!text.read (file_name))
00763 {
00764
00765 }
00766
00767 for (i = 0; i < branch_vector.size (); i++)
00768 {
00769 cmt_string& branch = branch_vector[i];
00770
00771
00772 command += "cvs -Q co ";
00773
00774
00775
00776 if (!at_head)
00777 {
00778 command += "-r ";
00779 command += version;
00780 }
00781
00782
00783 command += " -d ";
00784 command += branch;
00785 command += " ";
00786 command += module;
00787 command += "/";
00788 command += branch;
00789
00790 command += CmtSystem::command_separator ();
00791
00792 text += "D/";
00793 text += branch;
00794 text += "
00795 }
00796
00797 if (m_cmtcvstest)
00798 {
00799 cmt_string cvsroot;
00800
00801 CmtSystem::get_cvsroot (cvsroot);
00802
00803 cout << " cvsroot=" << cvsroot << " command[" << command << "]" << endl;
00804 }
00805
00806 if (CmtSystem::execute (command, out) == 0)
00807 {
00808 cout << "# Error getting package contents:" << endl;
00809 cout << out << endl;
00810 cout << "#---------------------------------------------------------" << endl;
00811 }
00812 else
00813 {
00814 if (!CmtSystem::test_directory ("CVS"))
00815 {
00821 //cout << "file_name=" << file_name << endl;
00822
00823 CmtSystem::mkdir ("CVS");
00824 cmt_string s;
00825
00826 // Let's create first the CVS/Root file.
00827
00828 CmtSystem::get_cvsroot (s);
00829 s += "\n";
00830
00831 cmt_string f;
00832
00833 f = "CVS";
00834 f += CmtSystem::file_separator ();
00835 f += "Root";
00836
00837 //cout << "f=" << f << " s=[" << s << "]" << endl;
00838 s.write (f);
00839
00840 // Now we create the CVS/Repository file
00841
00842 f = "CVS";
00843 f += CmtSystem::file_separator ();
00844 f += "Repository";
00845
00846 CmtSystem::get_cvsroot (s);
00847 if (s[0] == ':')
00848 {
00849 int pos = s.find (1, ":");
00850 s.erase (0, pos+1);
00851 pos = s.find (0, ":");
00852 s.erase (0, pos+1);
00853 }
00854 s += "/";
00855 s += module;
00856 s += "\n";
00857
00858 //cout << "f=" << f << " s=[" << s << "]" << endl;
00859 s.write (f);
00860 }
00861
00862 // Now the CVS/Entries is ready to be created.
00863 text.write (file_name);
00864 }
00865
00866 return (true);
00867 }
00868
00869 cmt_string find_matching_version (const cmt_string& expression)
00870 {
00871 cmt_string result;
00872
00873 //
00874 // Here expression takes the form
00875 // <some path>/<expression with wild-card>
00876 //
00877
00878 cmt_string dir;
00879 CmtSystem::dirname (expression, dir);
00880 dir += CmtSystem::file_separator ();
00881
00882 cmt_string version;
00883 CmtSystem::basename (expression, version);
00884
00885 if (version.find ("*") == cmt_string::npos)
00886 {
00887 // there is no wildcarding here. A simple test is enough.
00888 if (CmtSystem::test_directory (expression))
00889 {
00890 if (m_cmtcvstest) cout << "## Found direct match with " << version << endl;
00891 result = version;
00892 }
00893 else
00894 {
00895 if (m_cmtcvstest) cout << "## Explicit version " << version
00896 << " has no direct match" << endl;
00897 }
00898 }
00899 else
00900 {
00901 version.replace ("*", ".*");
00902
00903 cmt_regexp exp (version);
00904
00905 CmtSystem::cmt_string_vector list;
00906
00907 if (m_cmtcvstest) cout << "## Trying scan_dir dir=" << dir
00908 << " exp=" << version << endl;
00909
00910 CmtSystem::scan_dir (dir, exp, list);
00911
00912 if (list.size () > 0)
00913 {
00914 result = list[0];
00915
00916 if (m_cmtcvstest) cout << "## At least one version is matching " << version
00917 << "(" << list.size () << " matches) " << result << endl;
00918
00919 CmtSystem::basename (result, result);
00920 }
00921 else
00922 {
00923 if (m_cmtcvstest) cout << "## There is no version matching " << version << endl;
00924 }
00925 }
00926
00927 return (result);
00928 }
00929
00930 void checkout_package (const cmt_string& prefix,
00931 const cmt_string& package,
00932 const cmt_string& specified_version)
00933 {
00934 cmt_string version = specified_version;
00935 cmt_string empty;
00936 cmt_string full_prefix;
00937
00938 full_prefix = m_offset;
00939 full_prefix += prefix;
00940
00941 cmt_string echo_ppath;
00942
00943 if (full_prefix != "")
00944 {
00945 echo_ppath = " path ";
00946 echo_ppath += prefix;
00947 }
00948
00949 if (version == "")
00950 {
00951 cout << "# ================= No version specified for package " << package << endl;
00952 return;
00953 }
00954
00955 //
00956 // First make an attempt to locate the specified version of
00957 // this package "as-it-is" in the work area.
00958 // Since 'version' may contain wild-card, it's likely that
00959 // we should not simply use CmtSystem::test_directory but
00960 // use the wild-card search.
00961 //
00962
00963 cmt_string dir;
00964
00965 dir = build_version_directory (prefix, package, version);
00966
00967 if (m_cmtcvstest) cout << "## (testing dir= " << dir << ")" << endl;
00968
00969 bool recursive = m_recursive;
00970
00971 /*
00972 if (m_cmtcvstest)
00973 {
00974 cmt_string v = find_matching_version (dir);
00975
00976 cout << "---> v=" << v << endl;
00977 }
00978 */
00979
00980 //if (CmtSystem::test_directory (dir))
00981
00982 cmt_string effective_version = find_matching_version (dir);
00983
00984 if (effective_version != "")
00985 {
00986 version = effective_version;
00987
00988 dir = build_version_directory (prefix, package, version);
00989
00990 cout << "# ================= Package " << package
00991 << " version " << version << echo_ppath
00992 << " already installed." << endl;
00993
00994 recursive = false;
00995 }
00996 else
00997 {
00998 bool at_head = false;
00999 cmt_string module;
01000
01001 //
01002 // get_version attempts to find the most appropriate version
01003 // tag matching the specification FROM the repository. However,
01004 // we should take into account situations where some versions have
01005 // already been checked out, in which case they might be sufficient
01006 // (or preferred?)
01007 //
01008
01009 if (version.find ("*") != cmt_string::npos)
01010 {
01011 cout << "# ================= Package " << package
01012 << " version " << version << echo_ppath
01013 << " has wild cards and will not be considered." << endl;
01014 return;
01015 }
01016
01017 if (!get_version (full_prefix, package, version,
01018 module, version, at_head))
01019 {
01020 return;
01021 }
01022
01023 //cout << " full_prefix=[" << full_prefix << "] module=[" << module << "]" << endl;
01024
01025 if (m_cmtcvstest) cout << "## after get_version at_head=" << at_head << " m_head=" << m_head << endl;
01026
01027 if (m_head)
01028 {
01029 m_head = false;
01030
01031 at_head = true;
01032 }
01033 else
01034 {
01035 at_head = false;
01036 }
01037
01038 //
01039 // Make a second try after having selected a version from all the
01040 // available versions compatible with the specified version
01041 //
01042
01043 dir = build_version_directory (prefix, package, version);
01044
01045 if (CmtSystem::test_directory (dir))
01046 {
01047 cout << "# ================= Package " << package
01048 << " version " << version << echo_ppath
01049 << " already installed." << endl;
01050
01051 recursive = false;
01052 }
01053 else
01054 {
01055 //
01056 // Now we can say that we have to perform the real checkout.
01057 //
01058
01059 if (!really_checkout_package (prefix, package, version, module, dir, at_head))
01060 {
01061 cout << "# bad return from really_checkout_package" << endl;
01062 return;
01063 }
01064 }
01065 }
01066
01067 //
01068 // Now reach the newly checked out package.
01069 //
01070
01071 CmtSystem::cd (dir);
01072
01073 // Check if it is a true CMT package.
01074
01075 cmt_string file_name;
01076
01077 file_name = "cmt";
01078 file_name += CmtSystem::file_separator ();
01079 file_name += "requirements";
01080
01081 if (CmtSystem::test_file (file_name))
01082 {
01083 dir += CmtSystem::file_separator ();
01084 dir += "cmt";
01085 CmtSystem::cd ("cmt");
01086 }
01087 else
01088 {
01089 file_name = "mgr";
01090 file_name += CmtSystem::file_separator ();
01091 file_name += "requirements";
01092
01093 if (CmtSystem::test_file (file_name))
01094 {
01095 dir += CmtSystem::file_separator ();
01096 dir += "mgr";
01097 CmtSystem::cd ("mgr");
01098 }
01099 else
01100 {
01101 cout << "# " << package << " not a CMT package" << endl;
01102 return;
01103 }
01104 }
01105
01106 //cout << "# (recursive is " << recursive << ")" << endl;
01107
01108 if (recursive)
01109 {
01110 checkout_from_requirements ("requirements");
01111 }
01112 }
01113
01118 void checkout_from_requirements (const cmt_string& requirements_path)
01119 {
01120 static cmt_regexp expression ("^[ \t]*use[ \t]");
01121
01122 cmt_string text;
01123
01124 text.read (requirements_path);
01125
01126 RecursivePass1 p1;
01127 p1.run (text, expression);
01128
01129 RecursivePass2 p2 (*this);
01130 p2.run (p1.result ());
01131 }
01132
01133 void tags (const CmtSystem::cmt_string_vector& arguments)
01134 {
01135 if (arguments.size () < 1)
01136 {
01137 help ();
01138 return;
01139 }
01140
01141 if (CmtSystem::getenv ("CVSROOT") == "")
01142 {
01143 cout << "# Please set CVSROOT first !" << endl;
01144 return;
01145 }
01146
01147 if (CmtSystem::getenv ("CMTCVSTEST") != "")
01148 {
01149 m_cmtcvstest = true;
01150 }
01151 else
01152 {
01153 m_cmtcvstest = false;
01154 }
01155
01156 m_offset = CmtSystem::getenv ("CMTCVSOFFSET");
01157 if (m_offset != "")
01158 {
01159 m_offset += "/";
01160 m_offset.replace_all ("
01161 }
01162
01163 bool all = false;
01164
01165 for (int arg = 0; arg < arguments.size (); arg++)
01166 {
01167 const cmt_string& option = arguments[arg];
01168
01169 if (option == "-all")
01170 {
01171 all = true;
01172 }
01173 else
01174 {
01175 show_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), option);
01176
01177 if (error_info != "")
01178 {
01179 cout << error_info << endl;
01180 }
01181 else
01182 {
01183 cmt_string tags;
01184
01185 if (all)
01186 {
01187 tags = cvsversions_top_info;
01188 tags += " ";
01189 tags += cvsversions_info;
01190 }
01191 else
01192 {
01193 tags = tags_top_info;
01194 tags += " ";
01195 tags += tags_info;
01196 }
01197
01198 CmtSystem::cmt_string_vector v;
01199
01200 CmtSystem::split (tags, " \t", v);
01201 for (int i = 0; i < v.size (); i++)
01202 {
01203 const cmt_string& s = v[i];
01204 cout << s << endl;
01205 }
01206 }
01207 }
01208 }
01209 }
01210
01211 void branches (const cmt_string& module)
01212 {
01213 cmt_string out;
01214
01215 show_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), module);
01216
01217 if (error_info != "")
01218 {
01219 cout << error_info << endl;
01220 }
01221 else
01222 {
01223 cout << branches_info << endl;
01224 }
01225 }
01226
01227 void subpackages (const cmt_string& module)
01228 {
01229 cmt_string out;
01230
01231 show_cvs_infos (CmtSystem::getenv ("CMTCVSOFFSET"), module);
01232
01233 if (error_info != "")
01234 {
01235 cout << error_info << endl;
01236 }
01237 else
01238 {
01239 cout << subpackages_info << endl;
01240 }
01241 }
01242
01243 void help ()
01244 {
01245 cout << "> cd <some work area>" << endl;
01246 cout << "> cmt checkout [modifier ...] <package>" << endl;
01247 cout << "" << endl;
01248 cout << " modifier :" << endl;
01249 cout << " -l Do not process used packages (default)." << endl;
01250 cout << " -R Process used packages recursively." << endl;
01251 cout << " -r rev Check out version tag. (is sticky)" << endl;
01252 cout << " -d dir Check out into dir instead of module name." << endl;
01253 cout << " -o offset Offset in the CVS repository" << endl;
01254 cout << " -requirements <requirements file path> Check out packages referenced in this requirements file" << endl;
01255
01256
01257 cout << " --help print this help" << endl;
01258 cout << "" << endl;
01259 }
01260
01261 void do_checkout (const cmt_string& module, const cmt_string& version_tag)
01262 {
01263
01264
01265 History& h = History::instance ();
01266
01267 h.clear ();
01268
01269 if (module == "") return;
01270
01271 cmt_string prefix;
01272 cmt_string package;
01273 cmt_string version;
01274
01275 if (version_tag == "")
01276 {
01277 Cut cut (0);
01278
01279 cmt_string m;
01280 m = m_offset;
01281 m += module;
01282
01283 show_cvs_infos (m);
01284
01285 if (error_info != "")
01286 {
01287 cout << error_info << endl;
01288 return;
01289 }
01290
01291 if (tags_top_info != "") version = tags_top_info;
01292 else version = tags_info;
01293
01294
01295
01296 cut.run (version);
01297
01298 version = cut.result ();
01299
01300
01301 }
01302 else
01303 {
01304 version = version_tag;
01305 }
01306
01307 CmtSystem::dirname (module, prefix);
01308 CmtSystem::basename (module, package);
01309
01310 cmt_string top_dir;
01311
01312 top_dir = m_home_dir;
01313 top_dir += CmtSystem::file_separator ();
01314 top_dir += m_checkout_dir;
01315 top_dir += CmtSystem::file_separator ();
01316 top_dir += prefix;
01317 top_dir += CmtSystem::file_separator ();
01318 top_dir += package;
01319 top_dir += CmtSystem::file_separator ();
01320 top_dir += version;
01321
01322 checkout_package (prefix, package, version);
01323
01324
01325
01326 if (!CmtSystem::cd (top_dir)) return;
01327
01328 cmt_string file_name;
01329
01330 file_name = "cmt";
01331 file_name += CmtSystem::file_separator ();
01332 file_name += "requirements";
01333
01334 if (CmtSystem::test_file (file_name))
01335 {
01336 top_dir += CmtSystem::file_separator ();
01337 top_dir += "cmt";
01338 CmtSystem::cd ("cmt");
01339 }
01340 else
01341 {
01342 file_name = "mgr";
01343 file_name += CmtSystem::file_separator ();
01344 file_name += "requirements";
01345
01346 if (CmtSystem::test_file (file_name))
01347 {
01348 top_dir += CmtSystem::file_separator ();
01349 top_dir += "mgr";
01350 CmtSystem::cd ("mgr");
01351 }
01352 else
01353 {
01354 cout << "# " << package << "not a CMT package" << endl;
01355 return;
01356 }
01357 }
01358
01359
01360
01361 if (m_recursive)
01362 {
01363 CmtSystem::execute ("cmt broadcast cmt config");
01364 }
01365 else
01366 {
01367 CmtSystem::execute ("cmt config");
01368 }
01369 }
01370
01371 void checkout (const CmtSystem::cmt_string_vector& arguments)
01372 {
01373 if (arguments.size () < 1)
01374 {
01375 help ();
01376 return;
01377 }
01378
01379 if (CmtSystem::getenv ("CVSROOT") == "")
01380 {
01381 cout << "# Please set CVSROOT first !" << endl;
01382 return;
01383 }
01384
01385 if (CmtSystem::getenv ("CMTCVSTEST") != "")
01386 {
01387 m_cmtcvstest = true;
01388 }
01389 else
01390 {
01391 m_cmtcvstest = false;
01392 }
01393
01394 m_home_dir = CmtSystem::pwd ();
01395 m_checkout_dir = "";
01396 m_offset = "";
01397 m_branch_suffix = "";
01398
01399 cmt_string module;
01400
01401 m_recursive = false;
01402
01403 bool need_version_tag = false;
01404 cmt_string version_tag;
01405
01406 bool need_checkout_dir = false;
01407 bool need_offset = false;
01408 bool need_requirements_file = false;
01409
01410 bool simulation = false;
01411 bool verbose = false;
01412
01413 bool need_branch_suffix = false;
01414
01415 m_head = true;
01416
01417 m_offset = CmtSystem::getenv ("CMTCVSOFFSET");
01418 if (m_offset != "")
01419 {
01420 m_offset += "/";
01421 m_offset.replace_all ("//", "/");
01422 }
01423
01424 for (int arg = 0; arg < arguments.size (); arg++)
01425 {
01426 const cmt_string& option = arguments[arg];
01427
01428 if (need_version_tag)
01429 {
01430 need_version_tag = false;
01431
01432 if (option == "HEAD")
01433 {
01434 m_head = true;
01435 }
01436 else
01437 {
01438 version_tag = option;
01439 }
01440 }
01441 else if (need_checkout_dir)
01442 {
01443 need_checkout_dir = false;
01444 m_checkout_dir = option;
01445 }
01446 else if (need_offset)
01447 {
01448 need_offset = false;
01449 m_offset = option;
01450 m_offset += '/';
01451 m_offset.replace_all ("//", "/");
01452 }
01453 else if (need_branch_suffix)
01454 {
01455 need_branch_suffix = false;
01456 m_branch_suffix = "-";
01457 m_branch_suffix += option;
01458 }
01459 else if (need_requirements_file)
01460 {
01461 need_requirements_file = false;
01462 m_head = false;
01463 checkout_from_requirements (option);
01464 }
01465 else
01466 {
01467 if (option == "-R")
01468 {
01469 m_recursive = true;
01470 }
01471 else if (option == "-l")
01472 {
01473 m_recursive = false;
01474 }
01475 else if (option == "-r")
01476 {
01477 need_version_tag = true;
01478 m_head = false;
01479 }
01480 else if (option == "-d")
01481 {
01482 need_checkout_dir = true;
01483 }
01484 else if (option == "-o")
01485 {
01486 need_offset = true;
01487 }
01488 else if (option == "-n")
01489 {
01490 simulation = true;
01491 verbose = true;
01492 }
01493 else if (option == "-v")
01494 {
01495 verbose = true;
01496 }
01497 else if (option == "-branch")
01498 {
01499 need_branch_suffix = true;
01500 }
01501 else if (option == "-requirements")
01502 {
01503 need_requirements_file = true;
01504 }
01505 else if (option == "--help")
01506 {
01507 help ();
01508 return;
01509 }
01510 else if (option[0] == '-')
01511 {
01512 help ();
01513 return;
01514 }
01515 else
01516 {
01517 do_checkout (option, version_tag);
01518 }
01519 }
01520 }
01521
01522 }
01523
01524 private:
01525
01526 bool m_recursive;
01527 bool m_head;
01528 bool m_cmtcvstest;
01529
01530 cmt_string m_home_dir;
01531 cmt_string m_checkout_dir;
01532 cmt_string m_offset;
01533 cmt_string m_branch_suffix;
01534
01535 cmt_string error_info;
01536 cmt_string tags_top_info;
01537 cmt_string tags_info;
01538 cmt_string cvsversions_top_info;
01539 cmt_string cvsversions_info;
01540 cmt_string branches_info;
01541 cmt_string subpackages_info;
01542 };
01543
01544
01545
01546 void Grep::begin ()
01547 {
01548 m_result = "";
01549 }
01550
01551 void Grep::filter (const cmt_string& line)
01552 {
01553
01554
01555 if (m_result != "") m_result += " ";
01556 m_result += line;
01557 }
01558
01559 const cmt_string& Grep::result () const
01560 {
01561 return (m_result);
01562 }
01563
01564
01565
01566 Cut::Cut (int field)
01567 {
01568 m_field = field;
01569 }
01570
01571 void Cut::begin ()
01572 {
01573
01574 m_result = "";
01575 }
01576
01577 void Cut::filter (const cmt_string& line)
01578 {
01579
01580
01581 static CmtSystem::cmt_string_vector words;
01582
01583 CmtSystem::split (line, " \t", words);
01584
01585 if (words.size () <= m_field) return;
01586
01587 if (m_result != "") m_result += " ";
01588 m_result += words[m_field];
01589 }
01590
01591 const cmt_string& Cut::result () const
01592 {
01593 return (m_result);
01594 }
01595
01596
01597
01598
01599 History& History::instance ()
01600 {
01601 static History h;
01602 return (h);
01603 }
01604
01605 void History::clear ()
01606 {
01607 m_installed = "";
01608 }
01609
01610 void History::install (const cmt_string& line)
01611 {
01612 m_installed += "|";
01613 m_installed += line;
01614 m_installed += "|";
01615 }
01616
01617 bool History::is_installed (const cmt_string& line)
01618 {
01619 if (m_installed.find (line) != cmt_string::npos)
01620 {
01621 return (true);
01622 }
01623
01624 return (false);
01625 }
01626
01627 History::History ()
01628 {
01629 }
01630
01631
01632
01633
01634 void RecursivePass1::begin ()
01635 {
01636 m_first = true;
01637 m_result = "";
01638 }
01639
01640 void RecursivePass1::filter (const cmt_string& line)
01641 {
01642
01643
01644 if (line.find ("use CMT") != cmt_string::npos) return;
01645 if (line.find ("use cmt") != cmt_string::npos) return;
01646
01647 History& h = History::instance ();
01648
01649 if (h.is_installed (line)) return;
01650
01651 CmtSystem::cmt_string_vector words;
01652
01653 CmtSystem::split (line, " \t", words);
01654
01655 enum
01656 {
01657 need_package,
01658 need_version,
01659 need_path,
01660 no_need
01661 } state = need_package;
01662
01663 cmt_string package;
01664 cmt_string version;
01665 cmt_string path;
01666
01667 for (int i = 1; i < words.size (); i++)
01668 {
01669 const cmt_string& s = words[i];
01670
01671 if (s[0] == '-') continue;
01672
01673 switch (state)
01674 {
01675 case need_package:
01676 package = s;
01677 state = need_version;
01678 break;
01679 case need_version:
01680 version = s;
01681 state = need_path;
01682 break;
01683 case need_path:
01684 path = s;
01685 state = no_need;
01686 break;
01687 }
01688 }
01689
01690 if (version.find ("*") != cmt_string::npos)
01691 {
01692
01693
01694
01695
01696
01697 return;
01698 }
01699
01705 m_result += line;
01706 m_result += "\n";
01707
01708 if (m_first)
01709 {
01710 m_first = false;
01711 cout << " # --> now propagate cmt checkout to :" << endl;
01712 }
01713
01714 cout << " # " << package << " " << version << " " << path << endl;
01715 }
01716
01717 const cmt_string& RecursivePass1::result () const
01718 {
01719 return (m_result);
01720 }
01721
01722
01723
01724 RecursivePass2::RecursivePass2 (CvsImplementation& cvs) : m_cvs (cvs)
01725 {
01726 }
01727
01728 void RecursivePass2::begin ()
01729 {
01730 }
01731
01732 void RecursivePass2::filter (const cmt_string& line)
01733 {
01734
01735
01742 History& h = History::instance ();
01743
01744 if (h.is_installed (line)) return;
01745
01746 h.install (line);
01747
01748 CmtSystem::cmt_string_vector words;
01749
01750 CmtSystem::split (line, " \t", words);
01751
01752 enum
01753 {
01754 need_package,
01755 need_version,
01756 need_path,
01757 no_need
01758 } state = need_package;
01759
01760 cmt_string package;
01761 cmt_string version;
01762 cmt_string path;
01763
01764 for (int i = 1; i < words.size (); i++)
01765 {
01766 const cmt_string& s = words[i];
01767
01768 if (s[0] == '-') continue;
01769
01770 switch (state)
01771 {
01772 case need_package:
01773 package = s;
01774 state = need_version;
01775 break;
01776 case need_version:
01777 version = s;
01778 state = need_path;
01779 break;
01780 case need_path:
01781 path = s;
01782 state = no_need;
01783 break;
01784 }
01785 }
01786
01787 if (version.find ("*") != cmt_string::npos)
01788 {
01789
01790
01791
01792
01793
01794 }
01795 else
01796 {
01797 m_cvs.checkout_package (path, package, version);
01798 }
01799 }
01800
01801
01802
01803 void Cvs::tags (const CmtSystem::cmt_string_vector& arguments)
01804 {
01805 CvsImplementation cvs;
01806
01807 cvs.tags (arguments);
01808 }
01809
01810 void Cvs::branches (const cmt_string& module)
01811 {
01812 CvsImplementation cvs;
01813
01814 cvs.branches (module);
01815 }
01816
01817 void Cvs::subpackages (const cmt_string& module)
01818 {
01819 CvsImplementation cvs;
01820
01821 cvs.subpackages (module);
01822 }
01823
01824 void Cvs::checkout (const CmtSystem::cmt_string_vector& arguments)
01825 {
01826 CvsImplementation cvs;
01827
01828 cvs.checkout (arguments);
01829 }
01830