cmt_cvs.cxx Source File

Main Page Class Hierarchy Compound List File List Compound Members File Members

# cmt_cvs.cxx

Go to the documentation of this file.

    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     // This method exploits the hook installed into the loginfo script.
    00151     // A communication is setup with a dummy CVS module named .cmtcvsinfos/<module>
    00152     //
    00153     //  At import time, the contents of the file will be used to parameterize
    00154     // the script named cmt_buildcvsinfos2.sh (referenced in the loginfo script)
    00155     //
    00156     //  This script performs a scan in the CVS repository for currently 4 types of
    00157     // information :
    00158     //
    00159     //   all top symbolic tags installed for the module
    00160     //   all symbolic tags installed for the module
    00161     //   all branches available below this module
    00162     //   all subpackages installed below the module.
    00163     //
    00164     //    In principle, only modules corresponding to true CMT packages are considered.
    00165     //      o tags are obtained from the requirements file
    00166     //      o branches are sub-directories which are not themselves packages
    00167     //      o subpackages are sub-directories which are CMT packages
    00168     //        (a subdirectory is always either a branch or a subpackage)
    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           // Activities related with .cmtcvsinfos will occur in a temporary directory
    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           //trap "rm -rf ${tmp_dir}" 0 1 2 15
    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             # The script associated to such entries is supposed to :
    00226             #  1) extract the set of <infos> from the ${module}/cmt/requirements file
    00227             #  2) build an output of the form :
    00228             #      <infos>=info1 info2 info3 ...
    00229             #
    00230             # Currently this script can be found in
    00231             #
    00232             # ${CMTROOT}/cmt/cmt_buildcvsinfos2.sh
    00233             # %CMTROOT%/cmt/cmt_buildcvsinfos.py
    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           //cout << "# after cvsinfos out=[" << out << "]" << endl;
    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           //cout << "# (removing tmp_dir= " << tmp_dir << " home=" << home_dir<< ")" << endl;
    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     // Resolve all possible "aaa/bbb/../ccc/ddd" patterns into "aaa/ccc/ddd"
    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                   // xxxxx/yyy/../zzzz -> xxxxx/zzzz
    00436                   // 01234567890123456
    00437                   //       1234567
    00438                   //  pos   = 9
    00439                   //  slash = 5
    00440                   //  length = 9+3-5
    00441                   //
    00442                 d.erase (slash + 1, pos + 3 - slash);
    00443               }
    00444             else
    00445               {
    00446                   //
    00447                   // yyy/../zzzz -> zzzz
    00448                   // 01234567890
    00449                   // 1234567
    00450                   //  pos   = 3
    00451                   //  length = 3+1+3
    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 += "/"; // This is for CVS only
    00510             module.replace_all ("//", "/");
    00511           }
    00512
    00513         module += package;
    00514
    00529           //cout << " in get version : module=[" << module << "]" << endl;
    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               // We try on non-top versions
    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                       //  There was a wild card but the expression does not match
    00575                       // any of the existing tags in CVS.
    00576                       //  Things will be retreived from HEAD but we have to build
    00577                       // a reasonable version tag from the wild card expression.
    00578                       //  If the letter before the * was a digit, then simply remove
    00579                       // the * (v5* -> v5) otherwise add a zero (v5r* -> v5r0)
    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                               // "v5r*" -> "v5r0"
    00590                             version.replace ("*", "0");
    00591                           }
    00592                         else
    00593                           {
    00594                               // "v5*" -> "v5"
    00595                             version.replace ("*", "");
    00596                           }
    00597                       }
    00598                     else
    00599                       {
    00600                           // The expression was simply "*" !!!
    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           //cout << "-> status = " << status << " out=[" << out << "]" << endl;
    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               // This happens when there were no top files
    00765           }
    00766
    00767         for (i = 0; i < branch_vector.size (); i++)
    00768           {
    00769             cmt_string& branch = branch_vector[i];
    00770
    00771               //command += "cvs -Q co -P ";
    00772             command += "cvs -Q co ";
    00773
    00774 //            if (branch != "cmt")
    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 += "/";    // CVS uses the '/' notation on all platforms!!
    00788             command += branch;
    00789             //command += "\n";
    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           //cout << "   -n        simulation mode on" << endl;
    01256           //cout << "   -v        verbose mode on" << endl;
    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     //CMTPATH=${CMTPATH}:${m_home_dir}; export CMTPATH
    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           //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "version=" << version << endl;
    01295
    01296         cut.run (version);
    01297
    01298         version = cut.result ();
    01299
    01300           //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "version=" << version << endl;
    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     //cout << "after checkout_package pwd=[" << CmtSystem::pwd () << "] top_dir=[" << top_dir << "]" << endl;
    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     //cout << "end of checkout pwd=[" << CmtSystem::pwd () << "]" << endl;
    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     //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "Grep::filter" << endl;
    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     //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "Cut::begin" << endl;
    01574   m_result = "";
    01575 }
    01576
    01577 void Cut::filter (const cmt_string& line)
    01578 {
    01579     //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "Cut::filter" << endl;
    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     //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "RecursivePass1::filter" << endl;
    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       cout << "# ================= Package " << package
    01694            << " version " << version << " " << path
    01695            << " has wild cards and will not be considered." << endl;
    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     //if (CmtSystem::testenv ("CMTTESTAWK")) cout << "RecursivePass2::filter" << endl;
    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       cout << "# ================= Package " << package
    01791            << " version " << version << " " << path
    01792            << " has wild cards and will not be considered." << endl;
    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